package com.sw.mes.utils;

import com.sw.mes.core.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class EntityUtils {

    /**
     * 把一个List<Object[]>转换成一个List<T>
     *     getter/setter方法
     * @param objList
     * @param clz
     * @return
     * @throws Exception
     */
    public static <T> List<T> objectToBean(List<Object[]> objList, Class<T> clz) {
        if(objList==null || objList.size()==0) {
            return null;
        }

        List<T> list = new ArrayList<T>();
        try {
            for (Object[] o: objList) {
                //反射动态创建实例。
                Object obj = clz.newInstance();
                //实体中定义的全部属性。
                Field[] fields = clz.getDeclaredFields();
                //转换
                o = toJavaType(o);
                for(int i = 0; i < o.length; i++) {
                    String attName = fields[i].getName();

                    String firChar = String.valueOf(attName.charAt(0));

                    String attWord = attName.replaceFirst(firChar, firChar.toUpperCase());

                    //属性的setter方法
                    Method mth = clz.getDeclaredMethod("set" + attWord, fields[i].getType());

                    mth.invoke(obj, o[i]);
                }
                list.add((T) obj);
            }

        }catch (Exception e){
            e.printStackTrace();
        }

        return list;
    }

    /**
     * 把一个List<Object[]>转换成一个List<T>
     *     构造方法
     * @param objList
     * @param clz
     * @return
     * @throws Exception
     */
    public static <T> List<T> convToEntity(List<Object[]> objList, Class<T> clz) {
        if(objList==null || objList.size()==0) {
            return null;
        }

        Class<?>[] cz = null;
        Constructor<?>[] cons = clz.getConstructors();
        for(Constructor<?> ct : cons) {
            Class<?>[] clazz = ct.getParameterTypes();
            if(objList.get(0).length == clazz.length) {
                cz = clazz;
                break;
            }
        }

        List<T> list = new ArrayList<T>();
        try {
            for(Object[] obj : objList) {
                Constructor<T> cr = clz.getConstructor(cz);
                obj = toJavaType(obj);
                list.add(cr.newInstance(obj));
            }
        } catch (Exception ex){
            ex.printStackTrace();
        }
        return list;
    }

    /**
     * 将Object中数据类型不匹配的属性转换成相应属性
     * @param objects
     * @return
     */
    public static Object[] toJavaType(Object[] objects){

        Object[] array = new Object[objects.length];

        if(objects != null && objects.length > 0){
            for (int i = 0; i < objects.length; i++) {
                Object o = objects[i];
                if(o == null){
                    array[i] = o;
                    continue;
                }
                if("java.math.BigInteger".equals(o.getClass().getTypeName())){
                    o = ((BigInteger)o).longValue();
                }
                array[i] = o;
            }
        }
        return array;
    }


    /**
     * set属性的值到Bean
     * @param bean
     * @param value
     */
    public static Object setFieldValue(Object bean, String value, String fieldName) {
        Class<?> cls = bean.getClass();
        // 取出bean里的所有方法
        Method[] methods = cls.getDeclaredMethods();
        Field[] fields = cls.getDeclaredFields();

        for (Field field : fields) {
            try {
                if(fieldName.equals(field.getName())){
                    String fieldSetName = parSetName(fieldName);
                    if (!checkSetMet(methods, fieldSetName)) {
                        continue;
                    }
                    Method fieldSetMet = cls.getMethod(fieldSetName, field.getType());
                    if (null != value && !"".equals(value)) {
                        String fieldType = field.getType().getSimpleName();
                        if ("String".equals(fieldType)) {
                            fieldSetMet.invoke(bean, value);
                        } else if ("Date".equals(fieldType)) {
                            Date temp = DateUtil.toDate(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Integer".equals(fieldType) || "int".equals(fieldType)) {
                            Integer intval = Integer.parseInt(value);
                            fieldSetMet.invoke(bean, intval);
                        } else if ("Long".equalsIgnoreCase(fieldType)) {
                            Long temp = Long.parseLong(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Double".equalsIgnoreCase(fieldType)) {
                            Double temp = Double.parseDouble(value);
                            fieldSetMet.invoke(bean, temp);
                        } else if ("Boolean".equalsIgnoreCase(fieldType)) {
                            Boolean temp = Boolean.parseBoolean(value);
                            if("1".equals(value)) {
                                temp = true;
                            }
                            fieldSetMet.invoke(bean, temp);
                        } else {

                            if("Double[]".equalsIgnoreCase(fieldType)) {
                                fieldSetMet = cls.getMethod(fieldSetName, Double[].class);
                                value = value.replace("[", "").replace("]", "");
                                String[] t = value.split(",");
                                Double[] temp = new Double[t.length];
                                for (int i = 0; i < t.length; i++ ) {
                                    temp[i] = Double.valueOf(t[i]);
                                }
                                fieldSetMet.invoke(bean, (Object) temp);
                            }
                            if("String[]".equalsIgnoreCase(fieldType)) {
                                fieldSetMet = cls.getMethod(fieldSetName, String[].class);
                                value = value.replace("[", "").replace("]", "");
                                String[] temp = value.split(",");
                                fieldSetMet.invoke(bean, (Object) temp);
                            }

                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        return bean;
    }

    /**
     * 判断是否存在某属性的 set方法
     * @param methods
     * @param fieldSetMet
     * @return boolean
     */
    private static boolean checkSetMet(Method[] methods, String fieldSetMet) {
        for (Method met : methods) {
            if (fieldSetMet.equals(met.getName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 拼接在某属性的 set方法
     * @param fieldName
     * @return String
     */
    private static String parSetName(String fieldName) {
        if (null == fieldName || "".equals(fieldName)) {
            return null;
        }
        return "set" + fieldName.substring(0, 1).toUpperCase()
                + fieldName.substring(1);
    }

    /**
     * 拼接某属性的 get方法
     * @param fieldName
     * @return String
     */
    private static String parGetName(String fieldName) {
        if (null == fieldName || "".equals(fieldName)) {
            return null;
        }
        return "getIndex" + fieldName.substring(0, 1).toUpperCase()
                + fieldName.substring(1);
    }

    /**
     * 根据属性名获取属性值
     * @param fieldName
     * @param obj
     * @return
     */
    public static Object getValueByFieldName(String fieldName, Object obj) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static Object getClassByString(String clzName, String value) {

        try {
            Class clz = Class.forName(clzName);

            if (clz.isInstance(new Double(0D))) {
                return new Double(value);
            } else if (clz.isInstance(new Integer(0))) {
                return new Integer(value);
            } else if(clz.isInstance(new Long(0L))) {
                return new Long(value);
            } else {
                return new String(value);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Boolean getEvaluation(String org, String condition, String value1, String value2) {
        Boolean flag = false;

        if (StringUtils.isNotBlank(org) && StringUtils.isNotBlank(value1)) {
            PriorityQueue priorityQueue = new PriorityQueue(3);
            priorityQueue.insert(org);
            priorityQueue.insert(value1);

            switch (condition) {
                case ">":
                    if (priorityQueue.getIndex(value1) < priorityQueue.getIndex(org)) {
                        flag = true;
                    }
                    break;
                case ">=":
                    if ((priorityQueue.getIndex(value1) < priorityQueue.getIndex(org))
                            || value1.equalsIgnoreCase(org)) {
                        flag = true;
                    }
                    break;
                case "<":
                    if (priorityQueue.getIndex(value1) > priorityQueue.getIndex(org)) {
                        flag = true;
                    }
                    break;
                case "<=":
                    if ((priorityQueue.getIndex(value1) > priorityQueue.getIndex(org))
                            || value1.equalsIgnoreCase(org)) {
                        flag = true;
                    }
                    break;
                case "=":
                    if (value1.equalsIgnoreCase(org)) {
                        flag = true;
                    }
                    break;
                case "!=":
                    if (!value1.equalsIgnoreCase(org)) {
                        flag = true;
                    }
                    break;
                case "-":
                    // 包含
                    if (StringUtils.isNotBlank(value2)) {
                        priorityQueue.insert(value2);
                        if (((priorityQueue.getIndex(value1) < priorityQueue.getIndex(org)) || value1.equalsIgnoreCase(org)) &&
                                ((priorityQueue.getIndex(value2) > priorityQueue.getIndex(org)) || value2.equalsIgnoreCase(org))) {
                            flag = true;
                        }
                    }
                    break;
                case "IN":
                    if (value1.contains(org)) {
                        flag = true;
                    }
                    break;
                default:
                    flag = false;
            }
        }

        return flag;
    }

}
