package org.springblade.manager.service.impl;


import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jfireel.expression.Expression;
import com.mixsmart.utils.CustomFunction;
import lombok.AllArgsConstructor;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.manager.dto.FormData;
import org.springblade.manager.entity.Formula;
import org.springblade.manager.entity.WbsParam;
import org.springblade.manager.entity.WbsTree;
import org.springblade.manager.mapper.FormulaMapper;
import org.springblade.manager.service.IFormulaService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author yangyj
 * @Date 2022/6/9 14:29
 * @description TODO
 */

@Service
@AllArgsConstructor
public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula> implements IFormulaService {

    private final WbsParamServiceImpl wpService;


    public final static String WP="WP";
    public final static String CHAIN="trees";
    public final static String FC="FC.";


    public static final String POLY_REG= "(avg|min|max|sum)\\([^)]+\\)";
    public static final  Pattern POLY = Pattern.compile(POLY_REG);
    public void execute( List<FormData> list ){
             Map<Boolean,List<FormData>> map = list.stream().collect(Collectors.partitioningBy(e->e!=null&&e.getFormula().getFormula().contains("E[")));
            List<FormData>total = new ArrayList<>();
            /*用来保存所有变量*/
            Map<String,Object> variables = new HashMap<>();

            Map<String,Object> currentMap = new HashMap<>();
            /*预设变量start*/
            List<WbsTree> trees = new ArrayList<>();
            for(int i=0;i<6;i++){
                 WbsTree t= new WbsTree();
                 t.setDeptName("第"+i+"层");
                 trees.add(t);
            }
            List<WbsParam> wps = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getWbsId,123456));
            Map<String,Object> wpMap= new HashMap<>();
            if(CollectionUtil.isNotEmpty(wps)){
                for(WbsParam p:wps){
                     wpMap.put(p.getK(),p.getV());
                }
            }
           /*预设变量end*/

             /*没有依赖的*/
             List<FormData> simple=map.get(false);
             if(CollectionUtil.isNotEmpty(simple)){
                 total.addAll(simple);
             }
            /*有依赖的*/
             List<FormData> rely= map.get(true);
             if(CollectionUtil.isNotEmpty(rely)){
                  sort(rely,((rely.size()+1)/2)*rely.size());
                  total.addAll(rely);
             }

            if(CollectionUtil.isNotEmpty(total)){
                currentMap.put(WP,wpMap);
                currentMap.put(CHAIN,trees.stream().map(WbsTree::getDeptName).collect(Collectors.toList()));
                Map<String,Object> E=new HashMap<>();
                currentMap.put("E",E);
                for(FormData fd:total){
                      /*存入数据*/
                      if(CollectionUtil.isNotEmpty(fd.getValues())){
                           Map<String,Object> tmpMap = new HashMap<>();
                           for(int i=0;i<fd.getValues().size();i++){
                              tmpMap.put("p"+i,fd.getValues().get(i));
                           }
                          E.put(fd.getCode(),fd.getValues().get(0));
                           Map<String,Object> tableMap = (Map<String, Object>) variables.get(fd.getCode());
                           if(tableMap==null){
                               tableMap= new HashMap<>();
                               variables.put(fd.getCode(),tableMap);
                           }
                           tableMap.put(fd.getGroupId().toString(),tmpMap);
                      }
                      /*预处理公式脚本*/
                      String tmp =fd.getFormula().getFormula();
                      tmp = tmp.replace(FC, CustomFunction.CLASS_CALL);
                      Matcher m = PP.matcher(tmp);
                      while (m.find()){
                        tmp= tmp.replace(m.group(),"'"+m.group()+"'");
                      }
                       Matcher m2 = P.matcher(tmp);
                    while (m2.find()){
                        tmp= tmp.replace(m2.group(),"'"+m2.group()+"'");
                    }
                      fd.getFormula().setFormula(tmp);
                }
                /*执行公式*/
                /*集合公式预处理*/
                for(FormData fd:total){
                    String formula=fd.getFormula().getFormula();
                    if(formula.contains(CustomFunction.CLASS_CALL+"avg(")||formula.contains(CustomFunction.CLASS_CALL+"min(")||formula.contains(CustomFunction.CLASS_CALL+"max(")||formula.contains(CustomFunction.CLASS_CALL+"sum(")){
                        Matcher m = POLY.matcher(formula);
                        while (m.find()){
                            Object data =   Expression.parse(m.group()).calculate(currentMap);
                            formula = formula.replace(m.group(),data.toString());
                        }
                    }
                }
                for(FormData fd:total){
                    if(Func.isNotBlank(fd.getFormula().getFormula())){
                        Object data =   Expression.parse(fd.getFormula().getFormula()).calculate(currentMap);
                        fd.getValues().add(new ArrayList<>(Collections.singletonList(data)));
                    }
                }
            }
        System.out.println("执行结束");
    }


    public static void slice(Map<String,Object> variables,String formula){
            int min =0;
        Map<String,Object> currentMap = new HashMap<>();
        Map<String,List<Object>> massMap = new HashMap<>();
        for(Map.Entry<String,Object> entry:variables.entrySet()){
                if(entry.getValue() instanceof  List){
                    List<Object> tmp = (List<Object>) entry.getValue();
                    if(min==0){
                        min=tmp.size();
                    }else{
                        min= Math.min(min,tmp.size());
                    }
                    massMap.put(entry.getKey(),tmp);
                }else{
                    currentMap.put(entry.getKey(),entry.getValue());
                }
        }
        for(int i=0;i<min;i++){
                for(Map.Entry<String,List<Object>> e:massMap.entrySet()){
                    currentMap.put(e.getKey(),e.getValue().get(i));
                }
            Object data  = Expression.parse(formula).calculate(currentMap);

        }
    }

    public static final String WP_REG= "(?<=P\\[)[^]]+(?=\\])";
    public static final  Pattern PP = Pattern.compile(WP_REG);

    /**
     * 依赖排序
     */
    public static final String ELE_CODE_REG= "(?<=E\\[)[^]]+(?=\\])";
    public static final  Pattern P = Pattern.compile(ELE_CODE_REG);
    public  static void sort( List<FormData> list,int n){
        /*System.out.println("剩余计算次数："+n+"次");*/
        if(move(list)&&n>0){
            sort(list,--n);
        }
    }
    public  static Boolean move( List<FormData> list){
        for(int i=0;i<list.size();i++){
            FormData f=list.get(i);
            Matcher m =P.matcher(f.getFormula().getFormula());
            List<String> cp =  new ArrayList<>();
            while (m.find()){
                cp.add(m.group());
            }
            Map<Boolean,List<FormData>>  map= list.stream().skip(i+1).collect(Collectors.partitioningBy(e->cp.contains(e.getCode())));
            List<FormData> match =map.get(true);
            if(CollectionUtil.isNotEmpty(match)){
                for(FormData r:match){
                    list.remove(r);
                }
                list.addAll(0,match);
                return true;
            }
        }
        return false;

    }



}










