package cn.com.victorysoft.business.util;

import lombok.SneakyThrows;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;

public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {

    /**
     * Bean相减，current - last
     * @param current 被减Bean
     * @param last 减Bean
     * @param <T> 类型
     * @return 比较值的Bean
     */
    @SneakyThrows
    public static <T> T subtract(T current, T last) {
        if (current == null || last == null) return null;

        Class<T> tClass = (Class<T>) current.getClass();
        T compare = tClass.newInstance();
        Field[] fields = tClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            // 非数字字段，则使用当前对象的值
            if (!isNumber(field)) {
                copyProperty(compare, field.getName(), field.get(current));
                continue;
            }
            Class<?> type = field.getType();
            // 一方为null则不能比较
            if (field.get(current) == null || field.get(last) == null) {
                continue;
            }
            if (type == Short.class) {
                copyProperty(compare, field.getName(), (Short)field.get(current) - (Short)field.get(last));
            }
            if (type == Integer.class) {
                copyProperty(compare, field.getName(), (Integer)field.get(current) - (Integer)field.get(last));
            }
            if (type == Long.class) {
                copyProperty(compare, field.getName(), (Long)field.get(current) - (Long)field.get(last));
            }
            if (type == Float.class) {
                copyProperty(compare, field.getName(), (Float)field.get(current) - (Float)field.get(last));
            }
            if (type == Double.class) {
                copyProperty(compare, field.getName(), (Double)field.get(current) - (Double)field.get(last));
            }
            if (type == BigDecimal.class) {
                BigDecimal currentValue = (BigDecimal) field.get(current);
                BigDecimal lastValue = (BigDecimal) field.get(last);
                copyProperty(compare, field.getName(), currentValue.subtract(lastValue));
            }
        }
        return compare;
    }

    /**
     * 合并Bean，将dest中为空、orig中不为空的字段，复制到dest
     */
    @SneakyThrows
    public static <T> void mergeBean(T dest, T orig) {
        BeanInfo beanInfo = Introspector.getBeanInfo(dest.getClass());
        for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
            if (descriptor.getWriteMethod() != null) {
                Object currentValue = descriptor.getReadMethod().invoke(dest);
                Object defaultValue = descriptor.getReadMethod().invoke(orig);
                if (defaultValue != null && currentValue == null) {
                    descriptor.getWriteMethod().invoke(dest, defaultValue);
                }
            }
        }
    }

    /**
     * 如果为null，创建空的bean，保证bean不为null
     */
    @SneakyThrows
    public static <T> T ensure(T bean, Class<T> tClass) {
        return bean == null ? tClass.newInstance() : bean;
    }

    public static boolean isNumber(Field field) {
        Class<?> type = field.getType();
        return type == Short.class
            || type == Integer.class
            || type == Long.class
            || type == Float.class
            || type == Double.class
            || type == BigDecimal.class;
    }

    public static boolean isDate(Field field) {
        Class<?> type = field.getType();
        return type == Date.class;
    }

}
