package project;

import java.awt.Color;
import java.awt.Font;
import java.awt.TextComponent;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.List;

import javax.swing.InputVerifier;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.JTextComponent;

public class FormConfiguration implements FormSaveListener {
	
	String[] labelNames;
	String[] fieldNames;
	Class<?>[] fieldClass;
	int[] verifiers;
	int[] directions;
	

	int[] fieldSize;
	Hashtable<Integer,List<String>> fieldOptionsValue;
	Hashtable<Integer,List<String>> fieldOptionsDisplay;
	Object formDataObject;
	Class<?> formClass;
	String formName;
	Color formColor;
	

	int totalFields;
	int gridSize;
	Repository repository;
	boolean isEdit=true;
	
	int newID;
	
	public FormConfiguration(){
		
	}
	
	public boolean isEdit() {
		return isEdit;
	}
	
	public Color getFormColor() {
		return formColor;
	}

	public void setFormColor(Color formColor) {
		this.formColor = formColor;
	}
	
	public void setEdit(boolean isEdit) {
		this.isEdit = isEdit;
	}

	public String getFormName() {
		return formName;
	}


	public void setFormName(String formName) {
		this.formName = formName;
	}
	
	public int[] getVerifiers() {
		return verifiers;
	}

	public void setVerifiers(int[] verifiers) {
		this.verifiers = verifiers;
	}
	
	public int[] getDirection() {
		return directions;
	}

	public void setDirection(int[] directions) {
		this.directions = directions;
	}
	
	public Class<?> getFormClass(){
		return formClass;
	}
	
	public void setRepository(Repository repository){
		this.repository=repository;
	}
	
	public void setFormClass(Class<?> formClass){
		this.formClass=formClass;
	}
	public void setLabelNames(String[] labelNames){
		this.labelNames=labelNames;
	}
	
	public void setFieldNames(String[] fieldNames){
		this.fieldNames=fieldNames;
	}
	
	public void setFieldClass(Class<?>[] fieldClass){
		this.fieldClass=fieldClass;
	}
	
	public void setFieldSize(int[] fieldSize){
		this.fieldSize=fieldSize;
	}
	
	public void setFieldOptionsValue(Hashtable<Integer,List<String>> fieldOptionsValue){
		this.fieldOptionsValue=fieldOptionsValue;
	}
	
	public void setFieldOptionsDisplay(Hashtable<Integer,List<String>> fieldOptionsDisplay){
		this.fieldOptionsDisplay=fieldOptionsDisplay;
	}
	
	public JComponent getLabel(int index){
		JLabel label=new JLabel(labelNames[index]);
		label.setFont( new Font("Aerial", Font.PLAIN, 12));
		return label;
	}
	
	public void setFormData(Object formDataObject){
		this.formDataObject=formDataObject;
	}
	
	public int getTotalFields(){
		return labelNames.length;
	}
	

	public int getGridSize(){
		return gridSize;
	}
	
	public void setGridSize(int gridSize){
		this.gridSize=gridSize;
	}
	
	public JComponent getField(int index){
		InputVerifier inputVerifier=null;
		if (index !=0){
			switch (verifiers[index]){
			case 1 : 	inputVerifier=new NumericVerifier();
						break;
			case 2 : 	inputVerifier=new TextVerifier();
						break;
			}
		}
			
		if (fieldClass[index]==JTextField.class){
			JTextField textField=new JTextField(fieldSize[index]);
			if (index==0) textField.setEnabled(false);
			textField.setInputVerifier(inputVerifier);
			return textField;
		}
		else if (fieldClass[index]==RoundedTextField.class){
			RoundedTextField roundedTextField=new RoundedTextField("",fieldSize[index]);
			if (index==0) roundedTextField.setEnabled(false);
			roundedTextField.setInputVerifier(inputVerifier);
			return roundedTextField;
		}
		else if (fieldClass[index]==RoundedTextArea.class){
			RoundedTextArea textArea=new RoundedTextArea(3,fieldSize[index]);
			textArea.setLineWrap(true);
			return textArea;
		}
		else if (fieldClass[index]==JTextArea.class){
			JTextArea textArea=new JTextArea(3,fieldSize[index]);
			textArea.setLineWrap(true);
			return textArea;
		}
		else if (fieldClass[index]==RadioButtons.class){
		//	System.out.println(fieldOptionsDisplay.get(index).get(0).getClass());
			int size=fieldOptionsDisplay.get(index).size();
			System.out.println("size= "+size);
			String[] options=new String[size];
			fieldOptionsDisplay.get(index).toArray(options);
			//String[] options=(String[])(fieldOptionsDisplay.get(index).toArray());
			System.out.println(fieldOptionsDisplay.get(index).get(0).getClass());
			return new RadioButtons(options,getDirection()[index]);
			
		}
		return null;
	}
	
	public JComponent getField1(int index){
		JComponent field=getField(index);
		if (field.getClass()!=RadioButtons.class){
			if (index==0){
				field.setEnabled(false);
			}
			else {
				field=(JTextComponent )getField(index);
				field.setEnabled(isEdit);
			}
		}
		return field;
		
	}
	
	

	public String getFieldValue(JComponent component, int index){
		
		if (fieldClass[index]==JTextField.class){
			return ((JTextField)component).getText();
		}
		else if (fieldClass[index]==RoundedTextField.class){
			return ((RoundedTextField)component).getText();
		}
		else if (fieldClass[index]==JTextArea.class){
			return ((JTextArea)component).getText();
		}
		else if (fieldClass[index]==RoundedTextArea.class){
			return ((RoundedTextArea)component).getText();
		}
		else if (fieldClass[index]==RadioButtons.class){
			String displayValue=((RadioButtons)component).getSelectedValue();
			List<String> displayList=fieldOptionsDisplay.get(index);
			int indexValue=displayList.indexOf(displayValue);
			List<String> valueList=fieldOptionsValue.get(index);
			if (indexValue!=-1) return valueList.get(indexValue);
		}
		return null;
	}
	
	
	
	public void bindForm(GenericForm3 form){
		for (int i=0;i< fieldNames.length;i++){
			if (formDataObject==null) {
				try {
					//formDataObject=formClass.newInstance();
					formIntialise(form );
					break;
				} catch (Exception e) {
					e.printStackTrace();
				} 
			}
			
			String methodName="get"+fieldNames[i];
			
			try {
				
				Class<?>[] parameters={};
				Object[] paramData={};
				
				Method method=formDataObject.getClass().getDeclaredMethod(methodName, parameters);
				Object obj =method.invoke(formDataObject, paramData);
				JComponent component =form.getFieldComponent(i);
				
				Method setTextMethod=component.getClass().getMethod("setText", String.class);
				if (component instanceof RadioButtons){
					obj=fromOptionValueToIndex(String.valueOf(obj),i);
				}
				setTextMethod.invoke(component,String.valueOf(obj));
				
			} catch (Exception e) {
					e.printStackTrace();
			  } 
			
		}
		
	}
	
	public int fromOptionValueToIndex(String value,int fieldIndex){
		List<String> options=(List<String>)fieldOptionsValue.get(fieldIndex);
		return options.indexOf(value);
		
	}
	
	public void bind(Object formDataObject,GenericForm3 form){
		setFormData(formDataObject);
		bindForm(form);
		
	}
	
	public  Class<?>[] getMethodParameters(String methodName){
		
		Method[] methods=formDataObject.getClass().getDeclaredMethods();
		for (int i=0;i<methods.length;i++){
			if (methods[i].getName().equals(methodName)){
				Class<?>[] parameters=methods[i].getParameterTypes();
				return parameters;
			}
		}
		return null;
	}
	
	public Object[] getMethodParametersValue(Class<?>[] parameters,String value){
		Object[] objectsValue=new Object[parameters.length];
		int count=0;
		for (int i=0;i<parameters.length;i++){
			if (parameters[i]==Integer.TYPE){
				if ((value==null) || (value.equals("")) ){
					objectsValue[count]=0;
					if (newID!=0){
						objectsValue[count]=newID;
						newID=0;
					}
				}
				else objectsValue[count]=Integer.valueOf(value);
			}
			else objectsValue[count]=value;
			count++;
		}
		return objectsValue;
	}
	
	private void formSave(GenericForm3 form){
		
		for (int i=0;i< fieldNames.length;i++){
			
			JComponent component =form.getFieldComponent(i);
			String value=getFieldValue(component, i);
			
			String methodName="set"+fieldNames[i];
			
			
			Class<?>[] parameters=getMethodParameters(methodName);
			Object[] paramData=getMethodParametersValue(parameters, value);
			
			try {
				Method method=formDataObject.getClass().getDeclaredMethod(methodName, parameters);
				method.invoke(formDataObject, paramData);
								
			} catch (Exception e) {
				e.printStackTrace();
			  } 
		}
		bindForm(form);
	}
	
	private void formIntialise(GenericForm3 form ){
		for (int i=0;i< fieldNames.length;i++){
			try {
				JComponent component =form.getFieldComponent(i);
				Method setTextMethod=component.getClass().getMethod("setText", String.class);
				if (component instanceof RadioButtons){
				}
				else setTextMethod.invoke(component,"");
				
			} catch (Exception e) {
					e.printStackTrace();
			  } 
			
		}
	}
	
	@Override
	public void FormSaveOccured(FormSaveEvent event) {
		if (formDataObject==null) {
			try {
				formDataObject=formClass.newInstance();
				newID=repository.saveNewRecord(formDataObject);
			} catch (Exception e) {
				e.printStackTrace();
			} 
		}
		
		GenericForm3  form=(GenericForm3)event.getSource();
		formSave(form);
		
		
	}
	
}
