package com.apobates.forum.strategy.exposure.config.impl;

import com.apobates.forum.core.entity.Board;
import com.apobates.forum.core.entity.BoardConfig;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberStatusEnum;
import com.apobates.forum.strategy.StrategyMode;
import com.apobates.forum.strategy.exception.CulpritorIllegalStatusException;
import com.apobates.forum.strategy.exception.ReadStrategyException;
import com.apobates.forum.strategy.exception.StrategyException;
import com.apobates.forum.strategy.exception.WriteStrategyException;
import com.apobates.forum.strategy.exposure.config.AbstractConfigStrategy;
import com.apobates.forum.strategy.exposure.config.ComplexConfigStrategyExector;
import com.apobates.forum.utils.lang.TriPredicate;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;

/**
 * 版块配置文件检测策略
 * 
 * @author xiaofanku
 * @since 20200806
 */
public final class BoardConfigStrategy extends AbstractConfigStrategy<Board, BoardConfig>{
    public final static BiFunction<Board, Member, BoardConfigStrategy.Builer> BUILDER = (entity, member)->new BoardConfigStrategy.Builer(entity, member);
    
    public final static class Builer{
        private final Board board;
        private final Member member;
        
        public Builer(Board board, Member member) {
            this.board = board;
            this.member = member;
        }
        
        public ComplexConfigStrategyExector<Board,BoardConfig> initial(BoardConfig entityConfig, StrategyMode mode)throws StrategyException{
            return new BoardConfigStrategy().initial(entityConfig, board, mode, member);
        }
    }
    
    @Override
    protected BiPredicate<Board, StrategyMode> checkEntity() { //B: config中的版块检查项目{checkSelf}
        return (Board entity, StrategyMode currentMode)->{
            if (StrategyMode.WRITE == currentMode) {
                if (!entity.isNormal()) {
                    throw new WriteStrategyException("版块当前的状态禁止写入操作");
                }
            }
            return true;
        };
    }
    
    @Override
    protected TriPredicate<BoardConfig, Member, StrategyMode> checkCulpritor() { //D: config中的会员检查项目{checkCulpritor()}
        return (BoardConfig entityConfig, Member currentMember, StrategyMode currentMode)->{
            if (StrategyMode.READ == currentMode) {
                return checkCulpritorRGForReadMode(currentMember, entityConfig);
            }
            if (StrategyMode.WRITE == currentMode) {
                return checkCulpritorStatusForWriteMode(currentMember) && checkCulpritorRGForWriteMode(currentMember, entityConfig);
            }
            return true;
        };
    }
    
    private static boolean checkCulpritorStatusForWriteMode(Member culpritor) throws StrategyException {
        if (culpritor.getId() <= 0) {
            throw new CulpritorIllegalStatusException("非在线会员禁止发布主题");
        }
        if (MemberStatusEnum.ACTIVE != culpritor.getStatus()) {
            throw new CulpritorIllegalStatusException("您当前状态不具备发布主题的权限");
        }
        return true;
    }
    
    private static boolean checkCulpritorRGForReadMode(Member culpritor, BoardConfig entityConfig){
        //组
        if (culpritor.getMgroup().getSymbol() < entityConfig.getReadLowMemberGroup().getSymbol()) {
            throw new ReadStrategyException("您当前的组不满足版块阅读要求");
        }
        //角色
        if (culpritor.getMrole().getSymbol() < entityConfig.getReadLowMemberRole().getSymbol()) {
            throw new ReadStrategyException("您当前的角色不满足版块阅读要求");
        }
        return true;
    }
    
    private static boolean checkCulpritorRGForWriteMode(Member culpritor, BoardConfig entityConfig){
        //配置文件是否是只读
        if(!entityConfig.isReadWrite()){
            throw new WriteStrategyException("版块配置文件开启了只读模式");
        }
        //组
        if (culpritor.getMgroup().getSymbol() < entityConfig.getWriteLowMemberGroup().getSymbol()) {
            throw new WriteStrategyException("您当前的组不满足版块写入要求");
        }
        //角色
        if (culpritor.getMrole().getSymbol() < entityConfig.getWriteLowMemberRole().getSymbol()) {
            throw new WriteStrategyException("您当前的角色不满足版块写入要求");
        }
        return true;
    }
}