package project;

import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class FormConfigurationV4<T> implements FormSaveListener {
	
	String[] labelNames;
	String[] fieldNames;
	Class<?>[] fieldClass;
	int[] fieldSize;
	Hashtable<Integer,List<String>> fieldOptionsValue;
	Hashtable<Integer,List<String>> fieldOptionsDisplay;
	T formDataObject;
	int totalFields;
	int gridSize;
	
	public FormConfigurationV4(){
		
	}

	
	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 setFieldSize(List<Integer> fieldSize){
		//fieldSize.toArray(this.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){
		return new JLabel(labelNames[index]);
	}
	
	public void setFormData(T 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){
		if (fieldClass[index]==JTextField.class){
			return new JTextField(fieldSize[index]);
		}
		else if (fieldClass[index]==RoundedTextField.class){
			return new RoundedTextField("",fieldSize[index]);
		}
		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){
			String[] options=(String[])(fieldOptionsDisplay.get(index).toArray());
			return new RadioButtons(options,1);
		}
		return null;
	}
	
	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);
			return valueList.get(indexValue);
		}
		return null;
	}
	
	
	
	public void bindForm(GenericForm3 form){
		for (int i=0;i< fieldNames.length;i++){
			if (formDataObject==null) break;
			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(T 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){
				objectsValue[count]=Integer.valueOf(value);
			}
			else objectsValue[count]=value;
			count++;
		}
		return objectsValue;
	}


	@Override
	public void FormSaveOccured(FormSaveEvent event) {
		System.out.println("I am in the Form Configurator");
		if (formDataObject==null){
			
		}
		
		GenericForm3  form=(GenericForm3)event.getSource();
		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 {
				//formDataObject.getClass().getDeclaredMethods()
				Method method=formDataObject.getClass().getDeclaredMethod(methodName, parameters);
				method.invoke(formDataObject, paramData);
								
			} catch (Exception e) {
				e.printStackTrace();
			  } 
		}
		
	}
	
}
