package com.hzya.frame.beanutil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @Content
 * @Author 👻👻👻👻👻👻👻👻👻👻 gjh
 * @Date 2022-11-28 10:27
 * @Version 1.0
 */
public class BeanUtil {

    static Logger logger = LoggerFactory.getLogger(BeanUtil.class);

    public static String getBean() {
        return "232";
    }

    /**
     * 忽略大小写的bean copy方法
     *
     * @author liuyang
     */
    public static <T> T copyProperties(Object source, Object target) {
        Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass());
        CacheFieldMap.getFieldMap(target.getClass()).values().forEach((it) -> {
            logger.info(it.getName());
            Field field = sourceMap.get(it.getName().toLowerCase().replace("_", ""));
            if (field != null) {
                it.setAccessible(true);
                field.setAccessible(true);
                try {
                    //忽略null
                    if (field.get(source) != null) {
                        if ("java.lang.Long".equals(it.getType().getName())) {
                            it.set(target, Long.valueOf(field.get(source) + ""));
                        } else {
                            it.set(target, field.get(source));
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
        return (T) target;
    }

    /**
     * 忽略大小写的 bean copy 方法，可获取父类字段
     *
     * @author liuyang
     */
    public static <T> T copyPropertiesV2(Object source, Object target) {
        // 获取 target 及其父类的所有字段映射
        Map<String, Field> targetFieldMap = new HashMap<>();
        Class<?> currentClass = target.getClass();
        while (currentClass != null) {
            Map<String, Field> currentClassMap = CacheFieldMap.getFieldMap(currentClass);
            currentClassMap.forEach((key, value) -> targetFieldMap.put(key, value));
            currentClass = currentClass.getSuperclass();
        }

        Map<String, Field> sourceMap = CacheFieldMap.getFieldMap(source.getClass());

        targetFieldMap.values().forEach((it) -> {
            logger.info(it.getName());
            Field field = sourceMap.get(it.getName().toLowerCase().replace("_", ""));
            if (field != null) {
                it.setAccessible(true);
                field.setAccessible(true);
                try {
                    // 忽略 null
                    if (field.get(source) != null) {
                        if ("java.lang.Long".equals(it.getType().getName())) {
                            it.set(target, Long.valueOf(field.get(source) + ""));
                        } else {
                            it.set(target, field.get(source));
                        }
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        });
        return (T) target;
    }

    private static class CacheFieldMap {
        private static Map<String, Map<String, Field>> cacheMap = new HashMap<>();

        private static Map<String, Field> getFieldMap(Class clazz) {
            Map<String, Field> result = cacheMap.get(clazz.getName());
            if (result == null) {
                synchronized (CacheFieldMap.class) {
                    if (result == null) {
                        Map<String, Field> fieldMap = new HashMap<>();
                        for (Field field : clazz.getDeclaredFields()) {
                            fieldMap.put(field.getName().toLowerCase().replace("_", ""), field);
                        }
                        cacheMap.put(clazz.getName(), fieldMap);
                        result = cacheMap.get(clazz.getName());
                    }
                }
            }
            return result;
        }
    }
}
