package authoritymanager.client;

import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CellPanel;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class AddWidget {
	private static final String DEFAULT_WIDGET_HEIGHT	=	"25px" ;
	private String fieldName ;
	public Vector<AddWidget> children ;
	private String configuration ;
	private Widget widget ;
	private AuthorityManagerView view ;
	
	public AddWidget(final AuthorityManagerView view, String configuration) {
		super() ;
		this.view = view ;
		this.configuration = configuration ;
		this.children = new Vector<AddWidget>(1) ;
		this.fieldName = "" ;
		
		String [] st = split(configuration, '.') ; // configuration.split(".") ;
		if (!st [0].trim().equals("*")) {
			this.fieldName = st [0].trim() ;
		}
		else {
			this.fieldName = "" ;
		}
		int indexContent = st [1].indexOf("{") ;
		String content = indexContent == -1 ? "" : st [1].substring(indexContent + 1, st [1].lastIndexOf("}")) ;
		content = content.trim();
		String widgetType = indexContent == -1 ? st [1] : st [1].substring(0, indexContent) ;
		widgetType = widgetType.trim() ;
		String value = st [2].trim() ;
		if (value.equals("*")) {
			value = "" ;
		}
		String width = st [3].trim() ;
		if (width.equals("*")) {
			width = "" ;
		}
		else {
			width = width + "px" ;
		}
		if (widgetType.equals("edit")) {
			TextBox textBox = new TextBox() ;
			if (!width.equals("")) {
				textBox.setWidth(width) ;
			}
			textBox.setText(value) ;
			textBox.setHeight(DEFAULT_WIDGET_HEIGHT) ;
			widget = textBox ;
		}
		else {
			if (widgetType.equals("label")) {
				Label label = new Label(value) ;
				if (!width.equals("")) {
					label.setWidth(width) ;
				}
				label.setHeight(DEFAULT_WIDGET_HEIGHT) ;
				widget = label ;
			}
			else {
				if (widgetType.equals("+")) {
					FlexTable table = new FlexTable() ;					
					widget = table ;
					this.fieldName = "" ;
					final String confChild = st [0] + ".hpanel{" + content + "}.*." + st [3] ;
					final AddWidget child = new AddWidget(view, confChild) ;
					children.add(child) ;
					table.setWidget(0, 0, child.getWidget()) ;
					if (!width.equals("")) {
						table.getCellFormatter().setWidth(0, 0, width) ;
					}
					AddButton btnAdd = new AddButton(child, this.children) ;
					table.setWidget(0, 1, btnAdd) ;
				}
				else {
					if (widgetType.equals("hpanel") || widgetType.equals("vpanel")) {
						Panel panel = widgetType.equals("vpanel") ? new VerticalPanel() : new HorizontalPanel() ;
						widget = panel ;
						if (panel instanceof HorizontalPanel) {
							((HorizontalPanel) panel).setSpacing(3) ;
						}
						if (panel instanceof VerticalPanel) {
							((VerticalPanel) panel).setSpacing(1) ;
						}
						
						if (!width.equals("")) {
							panel.setWidth(width) ;
						}
						String [] stChild = split(content, ',') ; //content.split(",") ;
						for (int iChild = 0 ; iChild < stChild.length ; iChild ++) {
							String confChild = stChild [iChild].trim() ;
							AddWidget widgetChild = new AddWidget(view, confChild) ;
							children.add(widgetChild) ;
							panel.add(widgetChild.getWidget()) ;
						}
					}
					else {
						if (widgetType.equals("list")) {
							final ListBox list = new ListBox() ;
							list.setHeight(DEFAULT_WIDGET_HEIGHT) ;
							widget = list ;
							if (!width.equals("")) {
								list.setWidth(width) ;
							}
							String [] stContent = content.split("://") ;
							String location = stContent [0].trim().toUpperCase() ;
							
							if (location.equals("URL")) {
								String fileName = stContent [1]	;
								AsyncCallback<String> callback = new AsyncCallback<String>() {
									public void onFailure(Throwable caught) {
									}
									public void onSuccess(String result) {
										String [] values = result.split("\n") ;
										for (int iValue = 0 ; iValue < values.length ; iValue ++) {
											list.addItem(values [iValue].trim()) ;
										}
									}
								} ;	
								view.getController().getFile(fileName, callback) ;
							}
							if (location.equals("DATA")) {
								String [] values = stContent [1].split(",") ;
								for (int iValue = 0 ; iValue < values.length ; iValue ++) {
									list.addItem(values [iValue].trim()) ;
								}
							}
						}
					}
				}
			}
		}
	}
	
	private String [] split(String s, char delim) {
		Vector<String> res = new Vector<String>(4) ;
		int left = 0, curRes = 0 ;
		String current = "" ;
		for (int i = 0 ; i < s.length() ; i ++) {
			current += s.charAt(i) ;
			if (s.charAt(i) == '{') {
				left ++ ;
			}
			if (s.charAt(i) == '}') {
				left -- ;
			}
			if (s.charAt(i) == delim && left == 0) {
				res.add(current.substring(0, current.length() - 1)) ;
				current = "" ;
			}
		}
		res.add(current) ;
		String [] result = new String [res.size()] ;
		res.toArray(result) ;
		return result ;
	}
	
	public AddWidget clone() {
		return new AddWidget(view, configuration) ;
	}
	
	public void Disable() {
		if (widget instanceof TextBox) {
			((TextBox) widget).setEnabled(false) ;
		} else
		if (widget instanceof ListBox) {
			((ListBox) widget).setEnabled(false) ;
		} else
		if (widget instanceof FlexTable) {
			for (AddWidget addWidget: children) {
				addWidget.Disable() ;
			}
		} else
		if (widget instanceof Panel) {
			for (AddWidget addWidget: children) {
				addWidget.Disable() ;
			}
		}
		
	}
	
	public void Reset() {
		if (widget instanceof TextBox) {
			((TextBox) widget).setText("") ;
		} else
		if (widget instanceof ListBox) {
			((ListBox) widget).setSelectedIndex(0) ;
		} else
		if (widget instanceof FlexTable) {
			FlexTable table = (FlexTable) widget ;
			for (int iRow = table.getRowCount() - 2 ; iRow >= 0 ; iRow --) {
				table.removeRow(iRow) ;
				((Vector) children).remove(iRow) ;
			}
			for (AddWidget addWidget: children) {
				addWidget.Reset() ;
			}
		} else
		if (widget instanceof Panel) {
			for (AddWidget addWidget: children) {
				addWidget.Reset() ;
			}
		}
		
	}
	public void addChild(AddWidget addWidget) {
		if (widget instanceof CellPanel) {
			((Panel) widget).add(addWidget.getWidget()) ;
		}
		children.add(addWidget) ;
	}
	
	public Widget getWidget() {
		return widget ;
	}
	
	public DataSerial toDataSerial() {
		DataSerial dataSerial = new DataSerial() ;
		this.toDataSerial(dataSerial) ;
		return dataSerial ;
	}
	
	public void toDataSerial(DataSerial dataSerial) {
		if (widget != null) {
			if (widget instanceof TextBox) {
				TextBox textBox = (TextBox) widget ;
				if (textBox.getText().length() > 0) {
					dataSerial.put(fieldName, textBox.getText()) ;
				}
			} else
			if (widget instanceof ListBox) {
				ListBox listBox = (ListBox) widget ;
				dataSerial.put(fieldName, listBox.getValue(listBox.getSelectedIndex())) ;
			} else
			if (widget instanceof FlexTable) {
				DataSerial subData = null ;
				if (!fieldName.equals("")) {
					subData = new DataSerial() ;
				}
				for (int iChild = 0 ; iChild < children.size() - 1; iChild ++) {
					AddWidget child = children.get(iChild) ;
					if (subData != null) {
						child.toDataSerial(subData) ;
					}
					else {
						child.toDataSerial(dataSerial) ;
					}
				}
				if (subData != null && children.size() > 1) {
					dataSerial.put(fieldName, subData) ;
				}
				
			} else
			if (widget instanceof Panel) {
				DataSerial subData = null ;
				if (!fieldName.equals("")) {
					subData = new DataSerial() ;
				}
				for (AddWidget child: children) {
					if (subData != null) {
						child.toDataSerial(subData) ;
					}
					else {
						child.toDataSerial(dataSerial) ;
					}
				}
				if (subData != null) {
					dataSerial.put(fieldName, subData) ;
				}
			}
		}
		
			
	}
	
	public String GetConfiguration() {
		return this.configuration ;
	}
	
	public AuthorityManagerView GetView() {
		return this.view ;
	}

	
	public void setData(DataSerial record) {
		this.Reset() ;
		if (widget instanceof TextBox) {
			TextBox textBox = (TextBox) widget ;
			Collection values = record.get(this.fieldName)  ; 
			if (values != null) {
				String value = ((String) values.iterator().next()).trim() ;
				textBox.setText(value) ;
			}
			else {
				textBox.setText("") ;
			}
		} else
		if (widget instanceof ListBox) {
			ListBox listBox = (ListBox) widget ;
			Collection values = record.get(this.fieldName)  ; 
			String value = "" ;
			if (values != null) {
				value = ((String) values.iterator().next()).trim() ;				
			}
			int index = -1 ;
			for (int iList = 0 ; iList < listBox.getItemCount() && index == -1 ; iList ++) {
				if (listBox.getItemText(iList).toUpperCase().equals(value.toUpperCase())) {
					index = iList ;
				}
			}
			if (index == -1) {
				index = listBox.getItemCount() ;
				listBox.addItem(value) ;
				listBox.setSelectedIndex(index) ;
			}
		} else 
		if (widget instanceof FlexTable) {
			FlexTable table = (FlexTable) widget ;
			String field = this.fieldName ;
			if (field.equals("")) {
				do {
					AddWidget child = children.firstElement() ;
					field = child.fieldName ;
				}
				while (field.equals("")) ;
			}
			if (!field.equals("")) {
				Collection values = record.get(field) ;
				if (values != null) {
					for (Object value: values) {
						if (value instanceof DataSerial) {
							DataSerial childRecord = (DataSerial) value ;
							AddWidget child = children.lastElement() ;
							child.setData(childRecord) ;
							AddButton addBtn = (AddButton) table.getWidget(table.getRowCount() - 1, 1) ;
							addBtn.SetCurrent(false) ;
							AddWidget childClone = child.clone() ;
							children.add(childClone) ;
							int iRow = table.getRowCount() ;
							table.setWidget(iRow, 0, childClone.widget) ;
							AddButton btnAddClone = new AddButton(childClone, children) ;
							table.setWidget(iRow, 1, btnAddClone) ;
						}
					}
				}
			}
		} else 
		if (widget instanceof Panel) {
			Panel panel = (Panel) widget ;
			
			for (AddWidget child: children) {
				if (record.get(fieldName) == null) {
					child.setData(record) ;
				}
				else {
					Collection values = record.get(this.fieldName) ;
					if (values != null) {
						for (Object value: values) {
							if (value instanceof DataSerial) {
								child.setData((DataSerial) value) ;
							}
							else {
								int i = 1 ;
							}
						}
					}
				}				
			}
		}		
	}
	
}
	
	/*
	 * AsyncCallback<String> callback = new AsyncCallback<String>() {
									public void onFailure(Throwable caught) {
									}
									public void onSuccess(String result) {
										String [] values = result.split("\n") ;
										for (int iValue = 0 ; iValue < values.length ; iValue ++) {
											//list.addItem(values [iValue].trim()) ;
										}
									}
								} ;*/
