package org.matrix.actuators.util;


import com.alibaba.fastjson.JSON;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import org.matrix.actuators.env.EnvironmentActuator;
import org.matrix.actuators.move.MoveActuator;
import org.matrix.actuators.sql.SqlExpActuator;
import org.matrix.util.SpringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 补全http和检验点中的表达式的一些公共方法
 * @author huangxiahao
 */
@Component
public class CompleteExpressionUtil {

    public static final String JSON_PATH_REG = "\\{(\\s)*\\$.*?}|(<(\\s)*\\$.*?>)";

    public static final String ACTION_REG = "\\$(?=\\{(\\s)*(pre|mid|aft)[0-9]+\\.)(.*?)(?<=})(\\[(.*?)])?(\\<(.*?)>)?";

    public static final String ENV_VARIABLE_REG = "\\#\\{(.*?)}";

    public static final String DYNAMIC_VARIABLE_REG = "\\$\\{(((?!(pre|mid|aft)[0-9]+\\.).)*?)}(\\[(.*?)])?";

    public static final String PATH_REG = "(?<=[^(\\$)])\\{(.+?)\\}";

    public String completeVariable(String expression, Long envId, Long projectId) {
        String result = expression;
        result = regexExpression(
                result, ACTION_REG,
                null, (o, s) ->
                        getMoveActuator().parseMoveVar(s));
        result = regexExpression(
                result, DYNAMIC_VARIABLE_REG,
                null, (o, s) ->
                        getSqlExpActuator().parseVarByName(s,envId,projectId));
        result = regexExpression(
                result, ENV_VARIABLE_REG,
                null, (o, s) ->
                        getEnvironmentActuator().replaceEnvVar(s,envId));
        return result;
    }

    public String completePathVariable(String expression, Map<String, String> source,Long envId, Long projectId) {
        String result = expression;
        result = regexExpression(
                result, PATH_REG,
                source, (o, s) ->{
                    if (o instanceof Map){
                        String value = ((Map<String, String>)o).get(s.substring(1,s.length()-1));
                        if (value!=null&&!"".equals(value)){
                            completeVariable(value,envId,projectId);
                            return value;
                        }else {
                            return "";
                        }
                    }else {
                        return "";
                    }
                });
        return result;
    }

    /**
     *
     * @param expression jsonpath 表达式
     * @param jsonString json字符串
     * @return jsonpath解析结果
     */
    public String completeJsonPathExpression(String expression, String jsonString) {
        Object jsonObject = Configuration.defaultConfiguration().jsonProvider().parse(jsonString);
        return completeJsonPathExpression(expression,jsonObject);
    }

    /**
     *
     * @param jsonObject 这个Object 是由  Configuration.defaultConfiguration().jsonProvider().parse(“json字符串”);  这个方法转换过来的 请不要乱传
     * @return jsonpath解析结果
     */
    public String completeJsonPathExpression(String expression, Object jsonObject) {
        String result = expression;
        result = regexExpression(result, JSON_PATH_REG,
                jsonObject, (o, s) -> {
                    Object read = JsonPath.read(o, s.substring(1, s.length() - 1));
                    if (read instanceof String){
                        return (String) read;
                    }else {
                        return JSON.toJSONString(read);
                    }
                });
        return result;
    }

    public String regexExpression(String expression, String regex,Object sourceContent, BiFunction<Object,String,String> biFunction){
        Pattern pattern = Pattern.compile(regex);
        Matcher mat = pattern.matcher(expression);
        StringBuffer sBuffer=new StringBuffer();
        while (mat.find()) {
            String group = mat.group();
            String read = biFunction.apply(sourceContent,group);
            mat.appendReplacement(sBuffer,read);
        }
        mat.appendTail(sBuffer);
        return sBuffer.toString();
    }

    private static SqlExpActuator getSqlExpActuator(){
        return SpringUtils.getBean("sqlExpActuator");
    }

    private static EnvironmentActuator getEnvironmentActuator(){
        return SpringUtils.getBean("environmentActuator");
    }

    private static MoveActuator getMoveActuator(){
        return SpringUtils.getBean("moveActuator");
    }


}
