package com.gci.boot.common.util;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import lombok.extern.slf4j.Slf4j;

import java.lang.invoke.CallSite;
import java.lang.invoke.LambdaMetafactory;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;

@Slf4j
public class LambdaFunctionUtil {
    private static final int FLAG_SERIALIZABLE = 1;

    public static SFunction getFunctionField(Class<?> entityClass, String filedName) {
        Field field = ReflectUtil.getField(entityClass, filedName);
        final MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodType methodType = MethodType.methodType(field.getType(), entityClass);
        final CallSite site;
        if (StrUtil.isEmpty(filedName)){
            filedName = field.getName();
        }
        String getFunName = "get" + filedName.substring(0, 1).toUpperCase() + filedName.substring(1);
        try {
            site = LambdaMetafactory.altMetafactory(lookup,
                    "invoke",
                    MethodType.methodType(SFunction.class),
                    methodType,
                    lookup.findVirtual(entityClass, getFunName, MethodType.methodType(field.getType())),
                    methodType, FLAG_SERIALIZABLE);
            SFunction func = (SFunction) site.getTarget().invokeExact();
            return func;
        } catch (Throwable e) {
            log.error("根据字段获取sfunc异常:{},{}", e.getMessage(), e);
        }
        return null;
    }
}
