package util.componentInfo;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;

public class ComponentInfo {
	private static volatile ComponentInfo INSTANCE;
	private ComponentAttribute componentAttribute = new ComponentAttribute();
	private Object component = null;
	private String beanName;
	private String description;
	private String attribute;
	private String property;
	private boolean print;

	public ComponentInfo(String beanName) {
		this.beanName = beanName;
		this.attribute = "";
		this.property = "";
		print = true;
	}
	
	protected ComponentInfo() {
	}
	
	public String getName() {
		if (component == null)
			return null;
		return component.getClass().getName();
	}
	
	public void setComponentInfo(String attribute, String property) {
		this.attribute = attribute;
		this.property = property;
		this.description = "";
		if(print) printInfo();
	}
	
	public static ComponentInfo getInstance() {
		if (INSTANCE == null)
			synchronized (ComponentInfo.class) {
				if (INSTANCE == null)
					INSTANCE = new ComponentInfo();
			}
		return INSTANCE;
	}
	
	public void setComponentInfo(String attribute, String property, String description) {
		this.attribute = attribute;
		this.property = property;
		this.description = description;
		if(print) printInfo();
	}
	
	public static String toString(Object obj) {
		Class cl = obj.getClass();
		String r = cl.getName() + "[";
		Class sc = cl.getSuperclass();
		if (!sc.equals(Object.class))
			r += sc + ",";
		Field[] fields = cl.getDeclaredFields();
		try {
			AccessibleObject.setAccessible(fields, true);
		} catch (SecurityException e) {
		}
		for (int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			r += f.getName() + "=";
			try {
				Object val = f.get(obj);
				r += val.toString();
			} catch (IllegalAccessException e) {
				r += "???";
			}
			if (i < fields.length - 1)
				r += ",";
			else
				r += "]";
		}
		return r;
	}
	
	public void addField(Object component) {
		if (component == null)
			return;
		this.component = component;
		
		//if(ve.isLiteralText()) {ve.getExpressionString()} {ve.getValue(). }
		
		componentAttribute.cleanAll();
		String str = null;
		Field[] fields = component.getClass().getDeclaredFields();
		AccessibleObject.setAccessible(fields, true);
		for (Field field : fields) {
			if (!Modifier.isStatic(field.getModifiers())) {
				str = field.getName().substring(1);				
				if (str.startsWith("on")) {
					componentAttribute.putEvent(str,
							"");
				} else if (str.indexOf("tyle") != -1 || str.indexOf("lass") != -1) {
					try {
						//Object obj = field.get(component);
						UIComponentBase comp = (UIComponentBase) component;
						ValueExpression ve = comp.getValueExpression(str);
						if(ve != null){
						if(ve.isLiteralText()){
							componentAttribute.putStyle(str, ve == null ? "null" : ve.getExpressionString());
						} else{
							componentAttribute.putStyle(str, ve == null ? "null" : ve.getValue(FacesContext.getCurrentInstance().getELContext()).toString());
						}
						}
						
					} catch (IllegalArgumentException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				} else {
					
					try {
						Class cl = field.getType();
						if(cl.isPrimitive() || cl.getName().equals("java.lang.String")){
							UIComponentBase comp = (UIComponentBase) component;
							ValueExpression ve = comp.getValueExpression(str);
							if(ve != null){
							if(ve.isLiteralText()){
								componentAttribute.putAttribute(str, ve.getExpressionString());
							} else{
								componentAttribute.putAttribute(str, ve.getValue(FacesContext.getCurrentInstance().getELContext()).toString());
							}
							}
//							Object obj = field.get(component);
//							componentAttribute.putAttribute(str, obj == null ? "null" : obj.toString());
						} else componentAttribute.putAttribute(str, "---"); 
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					}
				}
			}
		}

	}

	public boolean isPrint() {
		return print;
	}

	public void setPrint(boolean print) {
		this.print = print;
	}

	public String [] getComponentInfo() {
		String [] str = {attribute, property};
		return str;
	}
	
	public String getAttribute() {
		return attribute;
	}

	public String getProperty() {
		return property;
	}
	
	private void printInfo() {
		System.out.println("beanName: " + beanName + "[attribute: " +  attribute + "; property: " + property + "; description: " + description + "];");
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Object getComponent() {
		return component;
	}

	public void setComponent(Object component) {
		this.component = component;
	}

	public ComponentAttribute getComponentAttribute() {
		return componentAttribute;
	}

	public void setComponentAttribute(ComponentAttribute componentAttribute) {
		this.componentAttribute = componentAttribute;
	}
}
