package cn.ibizlab.util.aspect;
 
import cn.ibizlab.util.annotation.RunLock;
import cn.ibizlab.util.annotation.VersionCheck;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.service.LockService;
import lombok.SneakyThrows;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
 
import java.lang.reflect.Method;
 
@Component
@Order(5000)
@Aspect
public class LockAspect {

    @Autowired
    @Lazy
    private LockService lockService;

    @SneakyThrows
    @Around("@annotation(runLock)")
    public Object checkLock(ProceedingJoinPoint point, RunLock runLock) {
        String targetName = point.getTarget().getClass().getName();
        String simpleName = point.getTarget().getClass().getSimpleName();
        String methodName = point.getSignature().getName();
        Object[] arguments = point.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String key = "";
        long lockTimeMillis=0L;
        String[] paramNames = {};
        for(Method method:methods){
            if(method.getName().equals(methodName)){
                key = runLock.value();
                lockTimeMillis=runLock.lockTimeMillis();
                paramNames = getParamterNames(method);
            }
        }
 
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(key);
        EvaluationContext context = new StandardEvaluationContext();
        for(int i=0;i<arguments.length;i++){
            context.setVariable(paramNames[i],arguments[i]);
        }
        String lockName=(expression.getValue(context,String.class));


        boolean locked=lockService.isLocked(lockName,lockTimeMillis);
        System.out.println(lockName+locked);
        if(locked)
            throw new BadRequestAlertException("服务正在执行中，已上锁",methodName,lockName);
        try {
            return point.proceed();
        }
        finally {
            if(!locked)
                lockService.unLock(lockName);
        }
    }
 
    public String[] getParamterNames(Method method){
        LocalVariableTableParameterNameDiscoverer u =
                new LocalVariableTableParameterNameDiscoverer();
        return  u.getParameterNames(method);
    }

 
}