//package com.tuoheng.common.core.config.redisson;
//
//import com.tuoheng.common.core.annotation.LockAction;
//import org.aspectj.lang.ProceedingJoinPoint;
//import org.aspectj.lang.annotation.Around;
//import org.aspectj.lang.annotation.Aspect;
//import org.aspectj.lang.annotation.Pointcut;
//import org.aspectj.lang.reflect.MethodSignature;
//import org.redisson.api.RLock;
//import org.redisson.api.RedissonClient;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
//import org.springframework.expression.EvaluationContext;
//import org.springframework.expression.ExpressionParser;
//import org.springframework.expression.spel.standard.SpelExpressionParser;
//import org.springframework.expression.spel.support.StandardEvaluationContext;
//import org.springframework.util.StringUtils;
//
//import java.lang.reflect.Method;
//import java.util.Locale;
//
///**
// * @author chenyukun
// */
//@Aspect
//@Configuration
//@ConditionalOnProperty(name = "spring.redis.consumer.enable", havingValue = "true")
//public class RedissonDistributedLockAspectConfiguration {
//
//    private final Logger logger = LoggerFactory.getLogger(RedissonDistributedLockAspectConfiguration.class);
//
//    @Autowired
//    @Qualifier("redissonClient")
//    private RedissonClient redissonClient;
//
//    private final ExpressionParser parser = new SpelExpressionParser();
//
//    private final LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
//
//    @Pointcut("@annotation(com.tuoheng.common.core.annotation.LockAction)")
//    private void lockPoint(){
//    }
//
//    @Around("lockPoint()")
//    public Object around(ProceedingJoinPoint pjp) throws Throwable{
//        Method method = ((MethodSignature) pjp.getSignature()).getMethod();
//        LockAction lockAction = method.getAnnotation(LockAction.class);
//        String key = lockAction.value();
//        String prefix = lockAction.prefix();
//        Object[] args = pjp.getArgs();
//        key = parse(key, method, args);
//        if(!StringUtils.hasLength(key) || !StringUtils.hasLength(prefix)){
//            logger.error("get key or prefix failed. key is null or prefix is null");
//            return null;
//        }
//        RLock lock = getLock(String.format(Locale.ENGLISH,"%s%s", prefix, key), lockAction);
//        if(!lock.tryLock(lockAction.waitTime(), lockAction.leaseTime(), lockAction.unit())) {
//            logger.debug("get lock failed [{}]", key);
//            return null;
//        }
//
//        //得到锁,执行方法，释放锁
//        logger.debug("get lock success [{}]", key);
//        try {
//            return pjp.proceed();
//        } finally {
//            lock.unlock();
//            logger.debug("release lock [{}]", key);
//        }
//    }
//
//    /**
//     * 解析spring EL表达式
//     * @param key 表达式
//     * @param method 方法
//     * @param args 方法参数
//     * @return string
//     */
//    private String parse(String key, Method method, Object[] args) {
//        String[] params = discoverer.getParameterNames(method);
//        if(params == null || params.length == 0){
//            return null;
//        }
//        EvaluationContext context = new StandardEvaluationContext();
//        for (int i = 0; i < params.length; i ++) {
//            context.setVariable(params[i], args[i]);
//        }
//        return parser.parseExpression(key).getValue(context, String.class);
//    }
//
//    private RLock getLock(String key, LockAction lockAction) {
//        switch (lockAction.lockType()) {
//            case REENTRANT_LOCK:
//                return redissonClient.getLock(key);
//
//            case FAIR_LOCK:
//                return redissonClient.getFairLock(key);
//
//            case READ_LOCK:
//                return redissonClient.getReadWriteLock(key).readLock();
//
//            case WRITE_LOCK:
//                return redissonClient.getReadWriteLock(key).writeLock();
//            default:
//                throw new RuntimeException("do not support lock type:" + lockAction.lockType().name());
//        }
//    }
//}
