package com.brilliance.isc.common.validator.es.support.impl;

import com.brilliance.mda.runtime.mda.util.MdaUtils;
import com.brilliance.isc.bo.Boprul;
import com.brilliance.isc.common.validator.es.factory.ScriptTemplateFactory;
import com.brilliance.isc.common.validator.es.support.IEsLoader;
import com.brilliance.isc.common.validator.es.vo.EnvDespVo;
import com.brilliance.isc.mda.dao.BoprulMapper;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.*;

@Component("esBopDBLoader")
public class BopDBLoader  implements IEsLoader {
    @Autowired
    private ScriptTemplateFactory scriptTemplateFactory;

    @Autowired
    private BoprulMapper boprulMapper;

    static String COMMON_JS = "";

    public String loadCommonJS() {
        if (COMMON_JS.isEmpty()) {
            synchronized (this) {
                if (!COMMON_JS.isEmpty()) {
                    return COMMON_JS;
                }

                //简单通过文件加载返回
                String scriptName = "common";
                String filePath = "es-script" + "/" + scriptName + ".js";
                Resource resource = new ClassPathResource(filePath);
                try (Reader commonReader = new InputStreamReader(resource.getInputStream());) {
                    String common_js = IOUtils.toString(commonReader);
                    if(!scriptTemplateFactory.isDebugMode()){
                        COMMON_JS = common_js;
                    }
                    return common_js;
                } catch (IOException e) {
                    throw new RuntimeException("fail to read " + scriptName + ".js");
                }
            }
        }else {
            return COMMON_JS;
        }
    }

    @Override
    public String loadEsScript(EnvDespVo envDespVo) {
        String common_js = loadCommonJS();
        String scriptName = envDespVo.getScriptName();
        Boprul boprul = new Boprul();
        boprul.setBoptbl(scriptName.toUpperCase());
        List<Boprul> boprulList = boprulMapper.selectValidByBoptbl(boprul);
        //输出规则
        //适用范围为空过滤掉
        Map<String,Map<String,List<String>>> transRules = new LinkedHashMap<>();
        boprulList.forEach(item->{
            //无范围
            if(MdaUtils.isEmpty(item.getRulscp())){
                return;
            }
            //无规则脚本
            if(MdaUtils.isEmpty(item.getChkrul())){
                return;
            }
            //按照scope按模块加载
            String[] scope = item.getRulscp().split(";");
            for (int i = 0; i < scope.length; i++) {
                String trans = firstUpper(scriptName)+firstUpper(scope[i]);
                Map<String,List<String>> transMap = transRules.get(trans);
                if(transMap == null){
                    transMap = new LinkedHashMap<>();
                    transRules.put(trans,transMap);
                }
                String fieldKey = item.getFldnam();
                if(!MdaUtils.isEmpty(item.getFldpth())){
                    fieldKey = item.getFldpth()+"."+ fieldKey;
                }
                List<String> rules = transMap.get(fieldKey);
                if(rules == null){
                    rules = new ArrayList<>();
                    transMap.put(fieldKey,rules);
                }
                String rule = item.getChkrul();
                rule = rule.replaceAll("let(\\s)","var$1").replaceAll("(\\([\\s,\\w]+\\))\\s*=\\s*>","function$1");
                if(rule.endsWith(",")){
                    rule = rule.substring(0,rule.length() - 1);
                }
                rules.add(rule);
            }

        });
        //输出模块
        StringBuilder sb =  new StringBuilder();
        StringBuilder expmod = new StringBuilder("\nvar expmod = {");
        for(Map.Entry<String,Map<String,List<String>>> entry: transRules.entrySet()){
            String transKey = entry.getKey();
            Map<String,List<String>> fieldRules = entry.getValue();
            String func = String.format("\nfunction %s(_this,moment,BigNumber){ return {",transKey);
            sb.append(func);
            expmod.append(String.format("%s:%s",transKey.toUpperCase(),transKey));
            expmod.append(",");
            for(Map.Entry<String,List<String>> fieldEntry:fieldRules.entrySet()){
                String field = fieldEntry.getKey();
                List<String> rules = fieldEntry.getValue();
                StringJoiner sj = new StringJoiner(",\n");
                rules.forEach(s -> sj.add("\t"+s));
                sb.append(String.format("\n'%s':[\n%s\n],",field,sj.toString()));
            }
            sb.append("\n}\n}");
        }
        expmod.append("}\n");
        sb.append(expmod);
        sb.append("function checkRule(){\n\treturn expmod[this.module]||function(){return {}}\n}");
        return sb.toString();
    }

    public String firstUpper(String word){
        return word.substring(0,1).toUpperCase()+
                word.substring(1).toLowerCase();
    }

    @Override
    public String getCurPath(String path) {
        return "classpath:"+path;
    }
}
