package helper.vo;

import com.alibaba.fastjson.TypeReference;
import com.yanzuoguang.util.base.ObjectHelper;
import com.yanzuoguang.util.vo.MapRow;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MapRowCache extends MapRow {
    private final static Map<String, TypeReference<?>> mapMethodReference = new ConcurrentHashMap<>();
    private final static Map<Class<?>, DataInfo> mapClassDataInfo = new ConcurrentHashMap<>();

    public MapRowCache() {
    }

    @Override
    public Object get(Object key) {
        return super.get(key);
    }

    @Override
    public Object put(String key, Object value) {
        return super.put(key, value);
    }

    protected <T> T getField(Get<T> getter) {
        DataInfo dataInfo = getDataInfo(getter.getClass(), 3);
        System.out.println(dataInfo.getName() + "()" + " called by " + dataInfo.getCls().getName());
        return null;
    }

    protected <T> void putField(Set<T> setter, T value) {
        DataInfo dataInfo = getDataInfo(setter.getClass(), 3);
        System.out.println(dataInfo.getName() + "()" + " called by " + dataInfo.getCls().getName());
    }

    private DataInfo getDataInfo(Class<?> cls, int pos) {
        if (!mapClassDataInfo.containsKey(cls)) {
            StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
            String methodName = stackTraceElements[pos].getMethodName();
            String fieldName = getMethodFieldName(methodName);
            String fieldClsName = getMethodFieldClsName(this.getClass(), fieldName);
            if (!mapMethodReference.containsKey(fieldClsName)) {
                throw new IllegalArgumentException("未注册类型:" + cls.getName() + " 方法关联:" + methodName);
            }
            DataInfo dataInfo = new DataInfo(methodName, cls, mapMethodReference.get(cls));
            mapClassDataInfo.put(cls, dataInfo);
            return dataInfo;
        }
        return mapClassDataInfo.get(cls);
    }

    private static String getMethodFieldClsName(Class<?> cls, String fieldName) {
        return cls.getName() + "." + fieldName;
    }

    protected static void register(Class<?> cls, String fieldName, TypeReference<?> typeReference) {
        String methodFieldClsName = getMethodFieldClsName(cls, fieldName);
        mapMethodReference.put(methodFieldClsName, typeReference);
    }

    protected interface Get<T> {
        T get();
    }

    protected interface Set<T> {
        void set(T t);
    }

    /**
     * 字段关联的数据信息
     */
    protected static class DataInfo {
        private final String name;
        private final Class<?> cls;
        private final TypeReference<?> typeReference;

        public DataInfo(String name, Class<?> cls, TypeReference<?> typeReference) {
            this.name = name;
            this.cls = cls;
            this.typeReference = typeReference;
        }

        public String getName() {
            return name;
        }

        public Class<?> getCls() {
            return cls;
        }

        public TypeReference<?> getTypeReference() {
            return typeReference;
        }
    }

    /**
     * 获取方法字段名
     *
     * @param fullName 方法全名
     * @return 方法字段名
     */
    protected String getMethodFieldName(String fullName) {
        return ObjectHelper.getMethodSimpleName(fullName);
    }
}