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

import com.apobates.forum.member.MemberProfileBean;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.strategy.StrategyMode;
import com.apobates.forum.strategy.exception.StrategyException;
import com.apobates.forum.strategy.exposure.config.impl.MemberProfilePlugStrategy;
import java.util.Arrays;
import java.util.function.Supplier;

/**
 * 复合配置文件策略执行器
 * 
 * @param <T> 实体
 * @param <C> 实体配置文件
 * @author xiaofanku
 * @since 20200806
 */
public final class ComplexConfigStrategyExector<T,C> {
    private final Member culpritor;
    private final T entity;
    private final StrategyMode mode;
    private final C entityConfig;
    
    public ComplexConfigStrategyExector(Member culpritor, T entity, StrategyMode mode, C entityConfig) {
        this.culpritor = culpritor;
        this.entity = entity;
        this.mode = mode;
        this.entityConfig = entityConfig;
    }
    /**
     * 进行会员等级信息策略检查
     * 
     * @param mpb 会员等级信息
     * @param profilePlugStrategy 会员等级信息的检查策略
     * @return
     * @throws StrategyException 
     */
    public ComplexConfigStrategyExector<T,C> profile(Supplier<MemberProfileBean> mpb, MemberProfilePlugStrategy<C> profilePlugStrategy) throws StrategyException{
        if(StrategyMode.READ == mode){
            profilePlugStrategy.readMode(entityConfig, mpb);
        }
        if(StrategyMode.WRITE == mode){
            profilePlugStrategy.writeMode(entityConfig, mpb);
        }
        return this;
    }
    /**
     * 执行扩展检测
     * 
     * @param function 接受三个特定类型的谓词函数:实体,实体配置文件,会员操作者
     * @return
     * @throws StrategyException 
     */
    public ComplexConfigStrategyExector<T,C> plug(ConfigPlugTriPredicate<T, C, Member> function) throws StrategyException{
        if(!Arrays.asList(function.allowModes()).contains(mode)){
            return this;
        }
        if(function.condition().get().test(entity, entityConfig, culpritor)){
            return this;
        }
        throw new StrategyException("扩展策略检测失败");
    }
    /**
     * 执行扩展检测
     * 
     * @param function 接受两个特定类型的谓词函数:实体配置文件,会员操作者
     * @return
     * @throws StrategyException 
     */
    public ComplexConfigStrategyExector<T,C> plug(ConfigPlugBiPredicate<C, Member> function) throws StrategyException{
        if(!Arrays.asList(function.allowModes()).contains(mode)){
            return this;
        }
        if(function.condition().get().test(entityConfig, culpritor)){
            return this;
        }
        throw new StrategyException("扩展策略检测失败");
    }
    
    public Member getCulpritor() {
        return culpritor;
    }
    
    public T getEntity() {
        return entity;
    }
    
    public StrategyMode getMode() {
        return mode;
    }
    
    public C getEntityConfig() {
        return entityConfig;
    }
}