package com.gx.obe.util.element;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.stream.Collectors;

import org.dom4j.Element;

import com.gx.obe.util.utils.ElementUtils;



public class FieldInfo {
	
	private String name;
	
	private Method writeMethod;
	
	private FieldType type;
	
	private Class<?> fClass;
	
	public FieldInfo(Field field, Method writeMethod) {
		this.name = field.getName();
		this.writeMethod = writeMethod;
		this.fClass = field.getType();
		if (fClass == String.class) this.type = FieldType.STRING;
		else if (fClass == List.class) {
			ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
			this.fClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
			this.type = fClass == String.class ? FieldType.LIST_STRING : FieldType.LIST_OBJECT;
		} else this.type = FieldType.OBJECT;
	}
	
	public void mapValue(Object obj, Element element) {
		Object value = getValue(element);
		if (value == null) return;
		try {
			writeMethod.invoke(obj, value);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {}
	}
	
	private Object getValue(Element element) {
		Element fieldElement = element.element(name);
		if (fieldElement == null) return null;
		List<?> elements = fieldElement.elements();
		switch (type) {
			case STRING:
				return fieldElement.getTextTrim();
			case OBJECT:
				return ElementClass.of(fClass).create(fieldElement);
			case LIST_STRING:
				return elements.stream().map(ElementUtils::as).map(Element::getTextTrim).collect(Collectors.toList());
			case LIST_OBJECT:
				return elements.stream().map(ElementUtils::as).map(ElementClass.of(fClass)::create).collect(Collectors.toList());
			default:
				return null;
		}
	}
	
	public enum FieldType {
		STRING, OBJECT, LIST_STRING, LIST_OBJECT;
	}
	
}