package com.ssyf.common.core.util;


import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.lang.func.LambdaUtil;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * 
 * @author huwei
 * @date 2022/12/13 10:28
 */
public class LambdaEnhanceUtil {

    /**
     * 获取字段名称
     * @param fn
     * @return
     */
    public static <T> String getFieldName(Function<T ,?> fn) {
        // 从function取出序列化方法
        Method writeReplaceMethod;
        try {
            writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }

        // 从序列化方法取出序列化的lambda信息
        boolean isAccessible = writeReplaceMethod.isAccessible();
        writeReplaceMethod.setAccessible(true);
        SerializedLambda serializedLambda;
        try {
            serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        writeReplaceMethod.setAccessible(isAccessible);

        // 从lambda信息取出method、field、class等
        String fieldName = serializedLambda.getImplMethodName();

        if(fieldName.startsWith("get")){
            fieldName = fieldName.substring("get".length());
        }else if(fieldName.startsWith("is")){
            fieldName = fieldName.substring("is".length());
        }

        return fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
    }

    /**
     * 获取字段名
     * @param fns
     * @return
     */
    public static <T> String[] getFieldNames(Function<T, ?>...fns){
        String[] result = new String[fns.length];
        for (int i = 0; i < fns.length; i++) {
            result[i] = getFieldName(fns[i]);
        }
        return result;
    }

    /**
     * 获取字段名
     * @param fns
     * @return
     */
    public static <T> List<String> getFieldNameList(Function<T ,?>...fns){
        List<String> result = new ArrayList<>();
        for (int i = 0; i < fns.length; i++) {
            result.add(getFieldName(fns[i]));
        }
        return result;
    }

    /**
     * 获取字段名
     * @param fns
     * @param <T>
     * @return
     */
    public static <T> String[] getFieldNames(Func1<T, ?>...fns){
        String[] result = new String[fns.length];
        for (int i = 0; i < fns.length; i++) {
            result[i] = LambdaUtil.getFieldName(fns[i]);
        }
        return result;
    }

    /**
     * 获取字段名
     * @param fns
     * @return
     */
    public static <T> List<String> getFieldNameList(Func1<T ,?>...fns){
        List<String> result = new ArrayList<>();
        for (int i = 0; i < fns.length; i++) {
            result.add(LambdaUtil.getFieldName(fns[i]));
        }
        return result;
    }
}
