package net.northking.cctp.element.basic.keywords;

import net.northking.cctp.element.basic.enums.ModeTypeEnum;
import net.northking.cctp.element.basic.utils.ContextUtil;
import net.northking.cctp.element.core.IExecuteContext;
import net.northking.cctp.element.core.annotation.Argument;
import net.northking.cctp.element.core.annotation.Keyword;
import net.northking.cctp.element.core.annotation.Keywords;
import net.northking.cctp.element.core.annotation.Return;
import net.northking.cctp.element.core.type.DataType;
import net.northking.cctp.element.core.type.InputType;

/**
 * 逻辑控制组件
 *
 * @author fengxiang.zhang
 * @since 1.0
 */
@Keywords
public class LogicControl {

    /**
     * <p>if表达式</p>
     * Example:
     * <pre>
     * if( ${var1} >= 1 && ${var1} < 3 ) {
     *     do something
     * }
     * else if( ${var1} >= 3 ) {
     *     do something
     * }
     * else {
     *     do something
     * }
     * </pre>
     *
     * @param expression 表达式: ${var1} == 1 && ${var2} > 3
     * @return 组件执行结果
     */
    @Keyword(alias = "if")
    @Return(name = "result", type = DataType.BOOLEAN, comment = "判断结果")
    public static boolean _if(
            @Argument(name = "mode", comment = "模式", type = DataType.ENUM, inputType = InputType.select, enumValues = ModeTypeEnum.class, defaultValue = "1") String mode,
            @Argument(name = "expression", comment = "表达式", type = DataType.STRING, expression = true) String expression,
            IExecuteContext context) {
        return ContextUtil.evalBooleanExpression(context, expression);
    }

    /**
     * <p>else if表达式</p>
     * Example:
     * <pre>
     * if( ${var1} >= 1 && ${var1} < 3 ) {
     *     do something
     * }
     * else if( ${var1} >= 3 ) {
     *     do something
     * }
     * else {
     *     do something
     * }
     * </pre>
     *
     * @param expression 表达式: ${var1} == 1 && ${var2} > 3
     * @return 组件执行结果
     */
    @Keyword(alias = "else if")
    @Return(name = "result", type = DataType.BOOLEAN, comment = "判断结果")
    public static boolean _else_if(
            @Argument(name = "mode", comment = "模式", type = DataType.ENUM, inputType = InputType.select, enumValues = ModeTypeEnum.class, defaultValue = "1") String mode,
            @Argument(name = "expression", comment = "表达式", type = DataType.STRING, expression = true) String expression,
            IExecuteContext context) {
        return ContextUtil.evalBooleanExpression(context, expression);
    }

    /**
     * <p>if表达式</p>
     * Example:
     * <pre>
     * if( ${var1} >= 1 && ${var1} < 3 ) {
     *     do something
     * }
     * else if( ${var1} >= 3 ) {
     *     do something
     * }
     * else {
     *     do something
     * }
     * </pre>
     *
     * @return 组件执行结果
     */
    @Keyword(alias = "else")
    @Return(name = "result", type = DataType.BOOLEAN, comment = "判断结果")
    public static boolean _else() {
        return true;
    }

    /**
     * <p>for表达式条件循环</p>
     * Example:
     * <pre>
     * for( ${var1} == 1 && ${var2} > 3, 10 )  = true
     * </pre>
     *
     * @param expression 条件表达式
     * @param maxNum     循环次数
     * @param context    执行上下文
     * @return 组件执行结果
     */
    @Keyword(alias = "条件循环")
    @Return(name = "result", type = DataType.BOOLEAN, comment = "执行结果")
    public static boolean _for(
            @Argument(name = "expression", type = DataType.STRING, comment = "表达式", expression = true) String expression,
            @Argument(name = "count", type = DataType.INTEGER, comment = "循环次数") Integer maxNum,
            IExecuteContext context) {
        int currentIndex = (Integer)context.getContextVariable("__forCurrentIndex");
        boolean result = maxNum > currentIndex;
        boolean expressionResult = ContextUtil.evalBooleanExpression(context, expression);
        return result && expressionResult;
    }

    /**
     * <p>跳出循环</p>
     * Example:
     * <pre>
     * for( ${var1} == 1 && ${var2} > 3, 10 )  {
     *     break(${var1} == 1);
     * }
     * </pre>
     *
     * @return 组件执行结果
     */
    public static boolean _break(
            @Argument(name = "expression", type = DataType.STRING, comment = "表达式", expression = true) String expression,
            IExecuteContext context) {
        boolean expressionResult = ContextUtil.evalBooleanExpression(context, expression);
        return expressionResult;
    }

}
