package com.apobates.forum.trident.controller.helper;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.CodeSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import com.apobates.forum.trident.exception.RequestLostTokenException;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.event.elderly.ForumActionEnum;
import com.apobates.forum.member.api.service.MemberOnlineService;
import com.apobates.forum.member.entity.MemberOnline;
import com.apobates.forum.member.storage.core.MemberSessionBean;
import com.apobates.forum.strategy.exception.VerificaFailException;
import com.apobates.forum.trident.OnlineDescriptor;
/**
 * OnlineDescriptor注解拦截器
 * Ajax时需要放出token,和出错时的提示
 * 
 * @author xiaofanku@live.cn
 * @since 20190625
 */
@Aspect
public class OnlineDescriptorAspect {
	@Autowired
	private MemberOnlineService memberOnlineService;
	//时间缓冲剂
	private final static MemberOnlineCreationCache mocc = MemberOnlineCreationCache.getSingleton();
	private final static Logger logger = LoggerFactory.getLogger(OnlineDescriptorAspect.class);
	
	@Before("@annotation(descriptor)")
	public void doPermissionCheck(JoinPoint joinPoint, OnlineDescriptor descriptor) {
		logger.info("[VD]EXE Sequence: 1");
		Object[] paramValues = joinPoint.getArgs();
		//动作是否是ajax
		boolean isAjax = descriptor.isAjax();
		//
		CodeSignature signature=(CodeSignature)joinPoint.getStaticPart().getSignature();
		String token = getTokenParameterValue(joinPoint.getArgs(), signature.getParameterNames());
		//高优先级检查:请求需要的参数是否完整
		//是ajax请求必需有token|非ajax不要求必需有token
		if(isAjax && "-1".equals(token)){
			throw new RequestLostTokenException("操作已被阻止, 原因: token参数丢失");
		}
		//token值的合法性检查
		if("0".equals(token) || !Commons.isNotBlank(token)){
			throw new VerificaFailException("非法的参数值token");
		}
		//在线身份检查:检查mbean是否合法
		MemberSessionBean mbean = null;
		//
		for (int i = 0; i < paramValues.length; i++) {
			if (paramValues[i] instanceof MemberSessionBean) {
				mbean = (MemberSessionBean) paramValues[i];
			}
		}
		//动作
		ForumActionEnum action = descriptor.action();
		//动作支持游客身份访问
		if(action.isSupportGuest()){
			return;
		}
		if(null==mbean){
			throw new VerificaFailException(action.getTitle()+"操作需要一个身份实例");
		}
		// ------------------------------------------会员在线记录
		MemberOnline mo = new MemberOnline(mbean.getMid(), mbean.getNickname(), action);
		// 不一定非要有一个存一个,N分钟内更新一次即可
		if (mocc.put(mo)) {
			memberOnlineService.create(mo);
		}
	}
	//返回方法参数中的token值,若不存在token参数返回-1
	private String getTokenParameterValue(Object[] paramValues, String[] paramNames) {
		String token = "-1";
		for (int i = 0; i < paramValues.length; i++) {
			if ("token".equals(paramNames[i].toLowerCase())) {
				try {
					token = (String) paramValues[i];
				} catch (ClassCastException e) {
					token = "0";
					logger.info("[CDA]loop token key fail, err: " + e.getMessage());
				}
			}
		}
		return token;
	}
}
