package com.fanruan.api.cal;

import com.fanruan.api.err.KitError;
import com.fanruan.api.util.GeneralKit;
import com.fr.base.BaseFormula;
import com.fr.base.ScriptFormula;
import com.fr.log.FineLoggerFactory;
import com.fr.script.Calculator;
import com.fr.stable.FormulaProvider;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.UtilEvalError;
import com.fr.stable.script.CalculatorProvider;
import com.fr.stable.script.Expression;
import com.fr.third.antlr.ANTLRException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author richie
 * @version 10.0
 * Created by richie on 2019-08-15
 * 公式计算相关的工具类
 */
public class FormulaKit {

    /**
     * 计算公式的值,会新建一个算子对象来计算该公式
     *
     * @param formula 公式内容
     * @return 公式计算后的结果值
     * @throws KitError 如果计算过程中出现错误,则抛出此异常
     */
    public static @Nullable Object eval(String formula) throws KitError {
        return eval(Calculator.createCalculator(), formula);
    }

    /**
     * 计算公式的值
     *
     * @param calculator 自定义算子
     * @param formula    公式内容
     * @return 公式计算后的结果值
     * @throws KitError 如果计算过程中出现错误,则抛出此异常
     */
    public static @Nullable Object eval(CalculatorProvider calculator, String formula) throws KitError {
        try {
            return BaseFormula.createFormulaBuilder().build(formula).eval(calculator);
        } catch (UtilEvalError u) {
            throw new KitError(u);
        }
    }

    /**
     * 生成公式对象
     *
     * @param content 公式的内容
     * @return 公式对象
     */
    public static @NotNull BaseFormula newFormula(Object content) {
        return BaseFormula.createFormulaBuilder().build(content);
    }

    /**
     * 生成脚本公式对象
     *
     * @param content 公式的内容,是一段javascript脚本
     * @return 脚本公式
     */
    public @NotNull static BaseFormula newScriptFormula(Object content) {
        return new ScriptFormula(GeneralKit.objectToString(content));
    }

    /**
     * 检查公式内容合法性
     *
     * @param content 公式文本
     * @return 如果非空且不合法返回false, 反之返回true
     */
    public static boolean checkFormulaContent(String content) {
        String formulaText = content.trim();

        if (StringUtils.isNotEmpty(formulaText)) {
            FormulaProvider formula = newFormula(formulaText);
            Expression expression = null;
            try {
                expression = formula.parse(Calculator.createCalculator());
            } catch (ANTLRException e) {
                FineLoggerFactory.getLogger().error(e.getMessage(), e);
            }
            return null != expression;
        }
        return true;
    }

    /**
     * 公式合法性校验
     *
     * @param formula 公式对象
     * @return 当前公式是否合法
     */
    public static boolean checkFormulaContent(FormulaProvider formula) {
        if (formula == null) {
            return true;
        }
        return checkFormulaContent(formula.getPureContent());
    }

    /**
     * 判断一个对象是否可以转化为公式
     * @param object 要判断的字符串
     * @return 如果该字符串是以"="开头,说明可以转化成公式,否则不能转化成公式
     */
    public static boolean canBeFormula(Object object){
        return StableUtils.canBeFormula(object);
    }

}