package com.engine.salary.formlua.util;

import com.alibaba.fastjson.JSONObject;
import com.engine.salary.formlua.entity.parameter.FormulaContext;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;


public class ExpressRegularUtil {
    private static final String[] checkRegularNullParameter = new String[]{"TRUE", "FALSE", "NOW", "TODAY"};
    private static final String[] operSymbs = new String[]{">", ">=", "=", "<", "<=", "\\+", "-", "\\*", "\\/", "!="};
    private static final String checkRegularParameter = "AND|OR|IF|NOT|LIKE|DATEDIFF|DATEADD|WEEKNUM|WEEKDAY|DATEFORMAT|Y|M|D|H|I|S|COUNT|SUM|MAX|MIN|CONCAT|SEARCH|TEXT|PAD|REPLACE|VALUE|LEN|LEFT|RIGHT|MID";
    private final static String leftCircleBracket = "Unmatched closing '('";
    private final static String rightCircleBracket = "Unmatched closing ')'";
    private final static String leftSquareBracket = "Unmatched closing '['";
    private final static String rightSquareeBracket = "Unmatched closing ']'";
    private final static String leftBigBracket = "Unmatched closing '{'";
    private final static String rightBigBracket = "Unmatched closing '}'";

    public static boolean checkFuncExpress(String str) {
        filter(str);
        return true;
    }

    public static boolean isContainChinese(String str) {
        Pattern p = Pattern.compile("[\u4E00-\u9FA5|\\！|\\，|\\。|\\（|\\）|\\《|\\》|\\“|\\”|\\？|\\：|\\；|\\【|\\】]");
        Matcher m = p.matcher(str);
        if (m.find()) {
            return true;
        }
        return false;
    }

    private static void filter(String formula) {
        try {
            testSymbol(formula);
            checkNullRegular(formula);
            checkOperatorNullParam(formula);
            formula = formula.replaceAll("", "#");
            String leftReplace = "";
            String rightReplace = "";
            leftReplace = formula.replaceAll("\\(", "");
            rightReplace = formula.replaceAll("\\)", "");
            if (leftReplace.length() > rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(leftCircleBracket, formula, formula.lastIndexOf(")"));
                throw patternSyntaxException;
            }
            if (leftReplace.length() < rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(rightCircleBracket, formula, formula.indexOf("("));
                throw patternSyntaxException;
            }

            leftReplace = formula.replaceAll("\\{", "");
            rightReplace = formula.replaceAll("}", "");
            if (leftReplace.length() > rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(leftBigBracket, formula, formula.lastIndexOf("}"));
                throw patternSyntaxException;
            }
            if (leftReplace.length() < rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(rightBigBracket, formula, formula.indexOf("{"));
                throw patternSyntaxException;
            }

            leftReplace = formula.replaceAll("\\[", "");
            rightReplace = formula.replaceAll("]", "");
            if (leftReplace.length() > rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(leftSquareBracket, formula, formula.lastIndexOf("]"));
                throw patternSyntaxException;
            }
            if (leftReplace.length() < rightReplace.length()) {
                PatternSyntaxException patternSyntaxException = new PatternSyntaxException(rightSquareeBracket, formula, formula.indexOf("["));
                throw patternSyntaxException;
            }

        } catch (PatternSyntaxException e) {
            String error = e.getDescription().trim();
            int errorIdx = e.getIndex();
            int errorEndIdx = -1;
            switch (error) {
                case leftCircleBracket:
                    error = "'('括号没有找到";
                    errorEndIdx = -1;
                    break;
                case rightCircleBracket:
                    error = "'('括号没有闭合";
                    errorEndIdx = -1;
                    break;
                case leftSquareBracket:
                    error = "'['括号没有找到";
                    errorEndIdx = -1;
                    break;
                case rightSquareeBracket:
                    error = "'['括号没有闭合";
                    errorEndIdx = -1;
                    break;
                case leftBigBracket:
                    error = "'{'括号没有找到";
                    errorEndIdx = -1;
                    break;
                case rightBigBracket:
                    error = "'{'括号没有闭合";
                    errorEndIdx = -1;
                    break;
                case "TRUE函数不能有参数":
                    errorEndIdx = errorIdx + 4;
                    break;
                case "FALSE函数不能有参数":
                    errorEndIdx = errorIdx + 5;
                    break;
                case "NOW函数不能有参数":
                    errorEndIdx = errorIdx + 3;
                    break;
                case "TODAY函数不能有参数":
                    errorEndIdx = errorIdx + 5;
                    break;

            }
            JSONObject catchJson = null;
            if (errorEndIdx < 0) {
                catchJson = ErrorUtil.buildError(formula, errorIdx + 1, null, error);
            } else {
                catchJson = ErrorUtil.buildError(formula, errorIdx + 1, errorEndIdx, null, error);
            }

            catchJson.put("formula", formula);
            throw new PatternSyntaxException(catchJson.toJSONString(), null, errorIdx + 1);
        }
    }

    private static void checkNullRegular(String formula) {
        String filterPattern = null;
        for (int i = 0; i < checkRegularNullParameter.length; i++) {
            int eidx = formula.indexOf(checkRegularNullParameter[i]);
            if (eidx >= 0) {
                if (FormulaContext.get().getValue(checkRegularNullParameter[i]) != null) {
                    Integer paramCount = FormulaContext.get().getValue(checkRegularNullParameter[i]);
                    paramCount++;
                    FormulaContext.get().setValue(checkRegularNullParameter[i]);
                } else {
                    FormulaContext.get().setValue(checkRegularNullParameter[i]);
                }
                filterPattern = checkRegularNullParameter[i] + "{1}\\({1}\\){1}";
                Pattern pattern = Pattern.compile(filterPattern);
                Matcher matcher = pattern.matcher(formula);
                boolean excuteBool = matcher.find();
                if (!excuteBool) {
                    eidx = 0;
                    Integer errorCount = FormulaContext.get().getFormulaJson().getInteger(checkRegularNullParameter[i]);
                    String[] errorCutArray = formula.split(checkRegularNullParameter[i]);
                    for (int fi = 0; fi < errorCount; fi++) {
                        eidx += errorCutArray[fi].length();
                        if (errorCutArray.length > 1 && fi > 0) {
                            eidx += checkRegularNullParameter[i].length();
                        }
                    }
                    PatternSyntaxException patternSyntaxException = new PatternSyntaxException(checkRegularNullParameter[i] + "函数不能有参数", formula, eidx);
                    throw patternSyntaxException;
                }
            } else {

            }
        }
    }

    private static void checkOperatorNullParam(String formula) {
        formula = formula.trim();
        JSONObject errorJson = new JSONObject();
        Map<String, Integer> operMap = new HashMap<>();

        for (int i = 0; i < operSymbs.length; i++) {
            String operSymb = operSymbs[i];
            if (formula.indexOf(operSymb) < 0) {
                continue;
            }
            if (operMap.get(operSymb) == null) {
                operMap.put(operSymb, 1);
            } else {
                operMap.put(operSymb, operMap.get(operSymb) + 1);
            }
            String commonP = "(" + operSymb + ")";
            Pattern wrongPone = Pattern.compile("^.+" + commonP + "+?$");
            Pattern wrongPtwo = Pattern.compile("^" + commonP + "+?.+$");
            Pattern wrongPthree = Pattern.compile("^" + commonP + "+?$");

            Matcher m = wrongPone.matcher(formula);

            if (m.find()) {
                errorJson = ErrorUtil.buildError(operSymb, formula.length(), operMap.get(operSymb), "操作符两端的参数不能为空");
                throw new RuntimeException(errorJson.getString("msg"));
            }

            Matcher mtwo = wrongPtwo.matcher(formula);
            if (mtwo.find()) {
                //-，负数特殊处理
                if (StringUtils.equals(operSymb, "-")) {
                    return;
                }
                errorJson = ErrorUtil.buildError(operSymb, 1, operMap.get(operSymb), "操作符两端的参数不能为空");
                throw new RuntimeException(errorJson.getString("msg"));
            }

            Matcher mthree = wrongPthree.matcher(formula);
            if (mthree.find()) {
                errorJson = ErrorUtil.buildError(operSymb, 1, operMap.get(operSymb), "操作符两端的参数不能为空");
                throw new RuntimeException(errorJson.getString("msg"));
            }

        }


    }

    public static void testSymbol(String formula) {
        Pattern pattern = Pattern.compile(",+?\\s*\\)");
        Matcher m = pattern.matcher(formula);
        if (m.find()) {
            int idx = formula.indexOf(m.group());
            PatternSyntaxException patternSyntaxException = new PatternSyntaxException("参数格式错误", formula, idx);
            throw patternSyntaxException;
        }
    }

    public static void main(String args[]) {

        checkOperatorNullParam(" abc>=");
    }


}
