package net.w_horse.excelpojo.bean;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import net.w_horse.excelpojo.ExcelPOJOException;

import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.SimpleTypeConverter;
import org.springframework.util.ClassUtils;

public class Utils {
	public static Object instantiateTarget(String targetClassName) throws ClassNotFoundException, LinkageError {
		Class<?> targetClass = ClassUtils.forName(targetClassName);
		return BeanUtils.instantiateClass(targetClass);
	}
	public static Object instantiateTarget(String targetClassName, Object[] args) throws ClassNotFoundException, LinkageError, BeanInstantiationException, SecurityException, NoSuchMethodException {
		Class<?> targetClass = ClassUtils.forName(targetClassName);
		return instantiateTarget(targetClass, args);
	}
	@SuppressWarnings("unchecked")
	public static <T>T instantiateTarget(Class<T> targetClass, Object[] args) throws ClassNotFoundException, LinkageError, BeanInstantiationException, SecurityException, NoSuchMethodException {
		Class<?>[] argTypes = new Class<?>[args.length];
		for (int i = 0; i < args.length; i++) {
			argTypes[i] = args[i].getClass();
		}

		return (T) BeanUtils.instantiateClass(targetClass.getDeclaredConstructor(argTypes), args);
	}
	public static Object convertIfNecessary(Object value, Class<?> requiredType) throws ExcelPOJOException {
		if (value == null) {
			if (requiredType.equals(int.class)
				|| requiredType.equals(long.class)
				|| requiredType.equals(double.class)
				|| requiredType.equals(short.class)
				|| requiredType.equals(float.class)
				|| requiredType.equals(byte.class)
			){
				return 0;
			} else if (requiredType.equals(boolean.class)){
				return false;
			} else if (requiredType.equals(char.class)){
				return '\u0000';
			} else {
				return null;
			}
		}

		if (!(value instanceof String)) {
			return (new SimpleTypeConverter()).convertIfNecessary(value, requiredType);
		}

		Object convertingValue = value;
		if (((String) value).length() == 0) {
			if (requiredType.equals(int.class)
				|| requiredType.equals(long.class)
				|| requiredType.equals(double.class)
				|| requiredType.equals(short.class)
				|| requiredType.equals(float.class)
				|| requiredType.equals(byte.class)
				|| requiredType.equals(Integer.class)
				|| requiredType.equals(Double.class)
				|| requiredType.equals(Short.class)
				|| requiredType.equals(Long.class)
				|| requiredType.equals(Float.class)
				|| requiredType.equals(BigDecimal.class)
				|| requiredType.equals(BigInteger.class)
				|| requiredType.equals(AtomicInteger.class)
				|| requiredType.equals(AtomicLong.class)
			){
				convertingValue = "0";
			} else if (requiredType.equals(boolean.class)
				|| requiredType.equals(Boolean.class)
			){
				convertingValue = "false";
			} else if (requiredType.equals(char.class)
				|| requiredType.equals(Character.class)
			){
				convertingValue = "";
			}
		}
		if (requiredType.equals(int.class)
				|| requiredType.equals(long.class)
				|| requiredType.equals(short.class)
				|| requiredType.equals(byte.class)
				|| requiredType.equals(Integer.class)
				|| requiredType.equals(Short.class)
				|| requiredType.equals(Long.class)
				|| requiredType.equals(BigInteger.class)
				|| requiredType.equals(AtomicInteger.class)
				|| requiredType.equals(AtomicLong.class)
		){
			int floatingPoint = ((String) value).indexOf(".");
			if (floatingPoint > 0) {
				convertingValue = ((String) value).substring(0, floatingPoint);
			}
		}
		return (new SimpleTypeConverter()).convertIfNecessary(convertingValue, requiredType);
	}
}
