package cn.axzo.workflow.core.common.utils;

import cn.axzo.workflow.common.model.request.bpmn.BpmnCondition;
import cn.axzo.workflow.core.common.exception.WorkflowEngineException;
import com.google.common.collect.Lists;

import java.util.List;
import java.util.Objects;

import static cn.axzo.workflow.core.common.code.ConvertorRespCode.CONVERTOR_OPERATION_CHECKBOX_TYPE_ERROR;
import static cn.axzo.workflow.core.common.code.ConvertorRespCode.CONVERTOR_OPERATION_NUMBER_TYPE_ERROR;
import static cn.axzo.workflow.core.common.code.ConvertorRespCode.CONVERTOR_OPERATION_RADIO_TYPE_ERROR;
import static cn.axzo.workflow.core.common.code.ConvertorRespCode.CONVERTOR_OPERATION_STRING_TYPE_ERROR;


/**
 * 表达式翻译器
 *
 * @author wangli
 * @since 2023/11/16 23:30
 */
public final class BpmnExpressionTranslator {
    private BpmnExpressionTranslator() {}

    public static String translateString(BpmnCondition condition) {
        // ${var:contains('variableName', 'hello')};
        // ${!var:contains('variableName', 'hello')}
        StringBuilder sb = new StringBuilder();
        if (Objects.equals(condition.getOperator(), "contains")) {
            sb.append("var:contains('")
                    .append(condition.getCode())
                    .append("', '")
                    .append(condition.getDefaultValue())
                    .append("')");
        } else if (Objects.equals(condition.getOperator(), "notContains")) {
            sb.append("!var:contains('")
                    .append(condition.getCode())
                    .append("', '")
                    .append(condition.getDefaultValue())
                    .append("')");
        } else {
            // 其他非法的操作符都过滤掉,或在这里抛出异常
            throw new WorkflowEngineException(CONVERTOR_OPERATION_STRING_TYPE_ERROR, condition.getOperator());
        }
        return sb.toString();
    }

    public static String translateNumber(BpmnCondition condition) {
        List<String> operators = Lists.newArrayList("eq", "ne", "gt", "gte", "lt", "lte", "between");
        if (operators.contains(condition.getOperator())) {

            StringBuilder sb = new StringBuilder();
            if ("between".equals(condition.getOperator())) {
                sb.append("var:")
                        .append(condition.getLeftOperator())
                        .append("('")
                        .append(condition.getCode())
                        .append("', ")
                        .append(condition.getLeftValue())
                        .append(")")
                        .append(" && ")
                        .append("var:")
                        .append(condition.getRightOperator())
                        .append("('")
                        .append(condition.getCode())
                        .append("', ")
                        .append(condition.getRightValue())
                        .append(")");
            } else {
                sb.append("var:")
                        .append(condition.getOperator())
                        .append("('")
                        .append(condition.getCode())
                        .append("', ")
                        .append(condition.getDefaultValue())
                        .append(")");
            }
            return sb.toString();
        } else {
            throw new WorkflowEngineException(CONVERTOR_OPERATION_NUMBER_TYPE_ERROR, condition.getOperator());
        }
    }

    public static String translateRadio(BpmnCondition condition) {
        if (Objects.equals(condition.getOperator(), "eq")) {
            return "var:" +
                    condition.getOperator() +
                    "('" +
                    condition.getCode() +
                    "', " +
                    condition.getDefaultValue() +
                    ")";
        } else {
            throw new WorkflowEngineException(CONVERTOR_OPERATION_RADIO_TYPE_ERROR, condition.getOperator());
        }
    }

    public static String translateCheckbox(BpmnCondition condition) {
        if (Objects.equals(condition.getOperator(), "in")) {
            StringBuilder sb = new StringBuilder("var:containsAny(")
                    .append("'")
                    .append(condition.getCode())
                    .append("', ");
            condition.getDefaultValues().forEach(i -> {
                sb.append("'").append(i).append("',");
            });
            sb.delete(sb.length() - 1, sb.length());
            sb.append(")");
            return sb.toString();
        } else {
            throw new WorkflowEngineException(CONVERTOR_OPERATION_CHECKBOX_TYPE_ERROR, condition.getOperator());
        }
    }

}
