package net.w_horse.excelpojo.xml;

import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.LinkedHashMap;

import net.w_horse.excelpojo.bean.Utils;
import net.w_horse.excelpojo.converter.CellFieldConverter;
import net.w_horse.excelpojo.converter.NothingConverter;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

public class ConverterFactoryBean implements FactoryBean {
	private String converterClassName;
	private HashMap<String, String> properties = new HashMap<String, String>();
	private LinkedHashMap<Integer, String> constractorArgs = new LinkedHashMap<Integer, String>();

	@Override
	public Object getObject() throws Exception {
		Class<? extends CellFieldConverter> converterClass = getObjectType();

		// コンストラクタで設定されていなかった場合
		// 引数は空の配列になり、デフォルトコンストラクタが実行される。
		Object[] args = new Object[getConstractorArgs().size()];
		for (Integer key : getConstractorArgs().keySet()) {
			args[key] = getConstractorArgs().get(key);
		}
		Object converter = Utils.instantiateTarget(converterClass, args);

		// プロパティで設定されていた場合
		for (String propertyName : getProperties().keySet()) {
			PropertyDescriptor propertyDescriptor
				= BeanUtils.getPropertyDescriptor(converterClass, propertyName);
			if (propertyDescriptor == null) {
				continue;	// 設定が実態と矛盾がある場合は無視する
			}
			ReflectionUtils.invokeMethod(propertyDescriptor.getWriteMethod(),
					converter,
					new Object[]{getProperties().get(propertyName)});
		}
		return converter;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Class<? extends CellFieldConverter> getObjectType() {
		Class<? extends CellFieldConverter> converterClass = NothingConverter.class;
		try {
			converterClass = ClassUtils.forName(getConverterClassName());
		} catch (ClassNotFoundException e) {
		} catch (LinkageError e) {
		}
		return converterClass;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}

	public void setConverterClassName(String converterClassName) {
		this.converterClassName = converterClassName;
	}

	public String getConverterClassName() {
		return converterClassName;
	}

	public void setProperties(HashMap<String, String> properties) {
		this.properties = properties;
	}

	public HashMap<String, String> getProperties() {
		return properties;
	}

	public void setConstractorArgs(LinkedHashMap<Integer, String> constractorArgs) {
		this.constractorArgs = constractorArgs;
	}

	public LinkedHashMap<Integer, String> getConstractorArgs() {
		return constractorArgs;
	}

}
