package thyyxxk.webserver.utils;

import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import thyyxxk.webserver.entity.login.UserInfo;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 描述
 * </p>
 *
 * @author xc
 * @date 2021-04-14 11:31
 */
@Slf4j
public class EntityCopy {

    @Data
    public static class Tes {
        private Integer code;
        private String empTitCode;
    }

    public static void main(String[] args) {
        UserInfo userInfo = new UserInfo();
        userInfo.setCodeRs("123");

        Tes userInfo1 = new Tes();
        userInfo1.setCode(1);
        userInfo1.setEmpTitCode("1222");

        CopyV2(userInfo, userInfo1);

        System.out.println(userInfo);
        System.out.println(userInfo1);
    }

    /**
     * 根据字段名，把右边的值，set到左边的对象中
     * @param dest 目标
     * @param source 来源
     */
    public static void CopyV2(Object dest, Object source) {
        if (source == null || dest == null) {
            return;
        }
        Map<String, Field> sourceFields = ReflectUtil.getFieldMap(source.getClass());
        Map<String, Field> destFields = ReflectUtil.getFieldMap(dest.getClass());

        for (Map.Entry<String, Field> field : sourceFields.entrySet()) {
            if (destFields.containsKey(field.getKey())) {
                Object fieldValue = ReflectUtil.invoke(source, StringUtil.getMethodName(field.getKey()));

                Field field1 = destFields.get(field.getKey());
                if (!field1.getType().equals(field.getValue().getType())) {
                    continue;
                }

                if (fieldValue != null) {
                    ReflectUtil.invoke(dest, StringUtil.setMethodName(field.getKey()), fieldValue);
                }
            }
        }
    }

    /**
     * @param source
     * @param dest
     * @throws Exception
     */
    public static void Copy(Object source, Object dest) throws Exception {
        if (source == null) {
            return;
        }
        // 获取属性
        BeanInfo sourceBean = Introspector.getBeanInfo(source.getClass(), java.lang.Object.class);
        PropertyDescriptor[] sourceProperty = sourceBean.getPropertyDescriptors();

        BeanInfo destBean = Introspector.getBeanInfo(dest.getClass(), java.lang.Object.class);
        PropertyDescriptor[] destProperty = destBean.getPropertyDescriptors();

        for (int i = 0; i < sourceProperty.length; i++) {
            // 调用source的getter方法和dest的setter方法
            try {
                if (isNull(destProperty[i].getReadMethod().invoke(dest)) && !isNull(sourceProperty[i].getReadMethod().invoke(source))) {
                    destProperty[i].getWriteMethod().invoke(dest, sourceProperty[i].getReadMethod().invoke(source));
                }
            } catch (Exception e) {
                throw new Exception("属性复制失败: 请不要使用 @Accessors(chain = true) 这个注解会导致,无法获取到写入方法.");
            }

        }

    }

    private static boolean isNull(Object value) {
        if (value == null) {
            return true;
        }
        return StringUtil.isBlank(value.toString());
    }

    /**
     * 注意  如果使用  @JSONField(name = xxx) 那么两个实体类都要有
     *
     * @param list  源对象
     * @param clazz class
     * @param <T>
     * @return
     */
    public static <T> List<T> CopyList(List<?> list, Class<T> clazz) {
        String oldOb = JSON.toJSONString(list);
        return JSON.parseArray(oldOb, clazz);
    }

    public static <T> T Copy(Object ob, Class<T> clazz) {
        String oldOb = JSON.toJSONString(ob);
        return JSON.parseObject(oldOb, clazz);
    }


    /**
     * 合并JSON对象，用source覆盖target，返回覆盖后的JSON对象。
     *
     * @param source JSONObject
     * @param target JSONObject
     * @return JSONObject
     */
    public static JSONObject jsonMerge(JSONObject source, JSONObject target) {
        // 覆盖目标JSON为空，直接返回覆盖源
        if (target == null) {
            return source;
        }

        for (String key : source.keySet()) {
            Object value = source.get(key);
            if (!target.containsKey(key)) {
                target.put(key, value);
            } else {
                if (value instanceof JSONObject) {
                    JSONObject valueJson = (JSONObject) value;
                    JSONObject targetValue = jsonMerge(valueJson, target.getJSONObject(key));
                    target.put(key, targetValue);
                } else if (value instanceof JSONArray) {
                    JSONArray valueArray = (JSONArray) value;
                    for (int i = 0; i < valueArray.size(); i++) {
                        JSONObject obj = (JSONObject) valueArray.get(i);
                        JSONObject targetValue = jsonMerge(obj, (JSONObject) target.getJSONArray(key).get(i));
                        target.getJSONArray(key).set(i, targetValue);
                    }
                } else {
                    target.put(key, value);
                }
            }
        }
        return target;
    }


}
