package com.sunxung.factoring.component.aspect;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.sunxung.factoring.component.annotation.Token;
import com.sunxung.factoring.component.cache.RedisCache;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.util.CodeUtil;
import com.sunxung.factoring.component.util.FormTokenUtil;
import com.sunxung.factoring.component.util.SpringUtil;

/**
 * @ClassName:TokenAspect
 * @Description:防止表单多次提交
 * @Author:duxiaojiao
 * @E-mail:1261237207@qq.com
 * @Date:2017年6月20日 下午8:47:02
 */
@Aspect
@Component
public class TokenAspect {

    private static Logger logger = LogManager.getLogger(TokenAspect.class);
    private static RedisCache redisCache;

    @SuppressWarnings("unused")
    @Before("within(@org.springframework.stereotype.Controller *) && @annotation(token)")
    public void testToken(final JoinPoint joinPoint, Token token) {
        try {
            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
            if (token != null) {
                // 获取 joinPoint 的全部参数
                Object[] args = joinPoint.getArgs();
                HttpServletRequest request = sra.getRequest();
                HttpServletResponse response = sra.getResponse();
                // boolean needSaveSession = token.save();
                // if (needSaveSession) {
                // String uuid = UUID.randomUUID().toString();
                // request.getSession().setAttribute("token", uuid);
                // logger.debug("进入表单页面，Token值为：" + uuid);
                // }
                boolean needRemoveSession = token.remove();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        throw new BusinessException(CodeUtil.FAIL, "表单不可重复提交");
                    }
                    getRedisCache().remove(request.getParameter(FormTokenUtil.TOKEN_NAME));
                }
            }
        } catch (BusinessException e) {
            logger.error("token 发生异常 : " + e);
            throw e;
        } catch (Exception e) {
            logger.error("token 发生异常 : " + e);
        }
    }

    private boolean isRepeatSubmit(HttpServletRequest request) throws BusinessException {
        // String serverToken = (String) request.getSession(false).getAttribute("token");
        String token = request.getParameter(FormTokenUtil.TOKEN_NAME);
        String serverToken = (String) getRedisCache().get(token);
        if (serverToken == null) {
            // throw new FormRepeatException("session 为空");
            return true;
        }
        String clinetToken = token;
        if (clinetToken == null || clinetToken.equals("")) {
            // throw new FormRepeatException("请从正常页面进入！");
            return true;
        }
        if (!serverToken.equals(clinetToken)) {
            // throw new FormRepeatException("重复表单提交！");
            return true;
        }
        logger.debug("校验是否重复提交：表单页面Token值为：" + clinetToken + ",Session中的Token值为:" + serverToken);
        return false;
    }

    private RedisCache getRedisCache() {
        if (redisCache == null) {
            redisCache = SpringUtil.getBeanByType(RedisCache.class);
        }
        return redisCache;
    }
}
