package com.apobates.forum.core.impl;

import java.util.Optional;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
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.core.api.dao.BoardDao;
import com.apobates.forum.core.api.dao.PostsDao;
import com.apobates.forum.core.api.dao.TopicDao;
import com.apobates.forum.core.entity.ActionEventDescriptor;
import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardActionCollection;
import com.apobates.forum.core.entity.Posts;
import com.apobates.forum.core.entity.Topic;
import com.apobates.forum.core.entity.TopicActionCollection;
import com.apobates.forum.event.elderly.ActionDescriptor;
import com.apobates.forum.event.elderly.ActionEventCulpritor;
import com.apobates.forum.utils.Commons;
import com.apobates.forum.utils.cache.AbstractCubbyHole;

/**
 * Core模块中关于ActionDescriptor注解拦截器
 * @author xiaofanku@live.cn
 * @since 20190329
 */
@Aspect
public class CoreModuleActionEventAspect {
	@Autowired
	private TopicDao topicDao;
	@Autowired
	private PostsDao postsDao;
	@Autowired
	private BoardDao boardDao;
	@Autowired
	private AbstractCubbyHole<ActionEventDescriptor> cubbyHole;
	//@Autowired
	//private BoardActionCollectionDao boardActionCollectionDao;
	//@Autowired
	//private TopicActionCollectionDao topicActionCollectionDao;
	private final static Logger logger = LoggerFactory.getLogger(CoreModuleActionEventAspect.class); 
	
    @Before("execution(* com.apobates.forum.core.impl.service.*.*(..)) && @annotation(actionDescriptor)")
    public void enjoy(JoinPoint joinPoint, ActionDescriptor actionDescriptor){
        logger.info("[CAT]12>1 method start");
    }
    
    @AfterReturning(
            pointcut="@annotation(actionDescriptor) && args(.., culpritor)",
            returning="retVal")
    public void check(
            JoinPoint joinPoint, 
            ActionEventCulpritor culpritor, 
            ActionDescriptor actionDescriptor, 
            Object retVal) throws Throwable{
        //方法名
        String methodName = joinPoint.getSignature().toShortString(); //TopicServiceImpl.browse(..)
        logger.info("[CAT]12>3 methodName: "+methodName);
        String[] classNameMethodName = methodName.replace("(..)", "").split("\\.");
        if(classNameMethodName == null || classNameMethodName.length != 2) {
            return;
        }
        //主键
        Long primaryKey;
        if(!actionDescriptor.isRedress()) {
            primaryKey = (Long)retVal;
        }else {
            //
            CodeSignature signature=(CodeSignature)joinPoint.getStaticPart().getSignature();
            primaryKey = getPrimaryKey(joinPoint.getArgs(), signature.getParameterNames(), actionDescriptor.keyName());
        }
        logger.info("[CAT]12>4 entity primary key value: "+primaryKey);
        if(classNameMethodName[0].startsWith("TopicService") || classNameMethodName[0].startsWith("PostsService")) {
            topicAndPostsAction(classNameMethodName[0], primaryKey, culpritor, actionDescriptor);
        }
        if(classNameMethodName[0].startsWith("BoardService")) {
            boardAction(primaryKey, culpritor, actionDescriptor);
        }
    }
    private void topicAndPostsAction(String className, Long id, ActionEventCulpritor culpritor, ActionDescriptor actionDescriptor) {
        if(id <= 0 || culpritor.getMemberId() <= 0) { 
            logger.info("[CAT]12>5 primary key args is Illegal");
            return;
        }
        long topicId=0;    //总有值
        long postsId=0L;   //回复时有值,话题时=0
        long victim=0L;    //总有值,回复时等于回复的会员,话题时等于发布话题的会员
        String topicTitle; //总有值
        
        if(className.contains("PostsService")) {
            postsId = id;
            Posts posts = postsDao.findOne(id).orElse(new Posts());
            topicId = posts.getTopicId();
            victim = posts.getMemberId();
        }else {
            topicId = id;
        }
        if(topicId <= 0) {
            logger.info("[CAT]12>6 topic primary key args is Illegal");
            return;
        }
        Topic topic = topicDao.findOne(topicId).orElse(new Topic());
        topicTitle = topic.getTitle();
        if(postsId > 0 && Commons.isNotBlank(topicTitle)) {
            topicTitle = "re:"+topic.getTitle();
        }
        if(postsId ==0 && victim==0) {
            victim = topic.getMemberId();
        }
        logger.info("[CAT]12>6.1 topic id: "+topicId+", title: "+topicTitle+", posts id: "+postsId);
        TopicActionCollection entity = new TopicActionCollection(actionDescriptor.action(), topicTitle, topicId, postsId, actionDescriptor.isRedress(), victim, culpritor);
        //topicActionCollectionDao.save(entity);
        cubbyHole.put(entity);
    }
    private void boardAction(Long primaryKey, ActionEventCulpritor culpritor, ActionDescriptor actionDescriptor) {
        if(culpritor.getMemberId() <= 0){
            logger.info("[CAT]12>6.9 member is guest");
            return ;
        }
        Optional<Board> obj = boardDao.findOne(primaryKey);
        if(!obj.isPresent()) {
            logger.info("[CAT]12>7 board primary key args is Illegal");
            return ;
        }
        Board board = obj.get();
        logger.info("[CAT]12>7.1 board id: "+board.getId()+", title: "+board.getTitle());
        BoardActionCollection entity = new BoardActionCollection(actionDescriptor.action(), board.getTitle(), primaryKey, actionDescriptor.isRedress(), 0L, culpritor);
        //boardActionCollectionDao.save(entity);
        cubbyHole.put(entity);
    }
    private Long getPrimaryKey(Object[] paramValues, String[] paramNames, String keyName) {
        Long key = -1L;
        for(int i=0;i<paramValues.length;i++){
            if(!"null".equalsIgnoreCase(keyName) && keyName.equals(paramNames[i])){
                try {
                    key = (Long)paramValues[i];
                }catch(ClassCastException e) {
                    logger.info("[CAT]12>3.1 loop primary key fail, err: "+e.getMessage());
                    key = 0L;
                }
            }
        }
        return key;
    }
}
