package com.brilliance.mda.runtime.mda.impl;

import com.brilliance.mda.runtime.mda.FieldHolder;
import com.brilliance.mda.runtime.mda.IDatafield;
import com.brilliance.mda.runtime.mda.IModule;
import com.brilliance.mda.runtime.mda.driver.MdaDriver;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class DatafieldImpl<T> implements IDatafield<T> {

	private IModule parent;
	private String name;
	private Field field;
	private Method setter;
	private Method getter;
	private String path;

	public DatafieldImpl(IModule parent, Field field)
	{
		this.parent = parent;
		this.name = field.getName();
		this.field = field;
		initField();
	}
	public DatafieldImpl(IModule parent, String fieldName)
	{
		this.parent = parent;
		this.name = fieldName;
		try{
			this.field = parent.getClass().getDeclaredField(fieldName);
		}catch (Exception e)
		{
			e.printStackTrace();
		}
		initField();
	}

	private void initField()
	{
		field.setAccessible(true);
		if(field.getType() == FieldHolder.class)
		{
			try{
				FieldHolder holder = (FieldHolder) field.get(parent);
				this.path = holder.getPath();
			}catch (Exception e)
			{

			}
		}
		else{
			String prefix = parent.getPath();
			if(prefix == null || prefix.length() ==0)
				this.path = this.name;
			else
				this.path = prefix + "." + this.name;
		}
		try {
			String gettStr = "get"+firstUpper(this.name);
			this.getter = parent.getClass().getMethod(gettStr);
		}catch (Exception e){}
		try {
			String settStr = "set" + firstUpper(this.name);
			if(this.getter!=null)
				this.setter = parent.getClass().getMethod(settStr,this.getter.getReturnType());
			else if(this.field != null)
				this.setter = parent.getClass().getMethod(settStr,this.field.getType());
		}catch (Exception e){}

	}
	public IModule getParent() {
		return parent;
	}
	public String getName() {
		return name;
	}
	@SuppressWarnings("unchecked")
	public T getValue() {
		try {
			if(this.getter != null)
			return (T)this.getter.invoke(parent);
		} catch (Exception e)
		{

		}
		return null;
	}
	public void setValue(T value) {
		try {
			if(this.setter != null)
				setter.invoke(parent,value);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Override
	public String getPath() {
		return this.path;
	}
	public void clear(){
		if(this.setter != null)
		{
			Class<?>[] clazz =  this.setter.getParameterTypes();
			if(clazz.length ==1)
			{
				Object obj = MdaDriver.zero(clazz[0]);
				try {
					this.setter.invoke(parent,obj);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

	}
	private String firstUpper(String str)
	{
		if(str.length()<=1)
			return str.toUpperCase();
		return str.substring(0,1).toUpperCase()+str.substring(1);
	}
	public Class<T> getDataType()
	{
		return (Class<T>)getter.getReturnType();
	}

	@Override
	public void setAttribute(Object k, Object v) {

	}

	@Override
	public Object getAttribute(Object k) {
		return null;
	}
}
