package com.steering.Demand.sever;

import CoreFS.SA08.CoreXmlSqlParsersFactory;
import com.steering.Demand.entity.TmsComRuleEntity;
import com.steering.Demand.entity.iRule;
import com.steering.comm.converter.EntityTool;

import javax.script.*;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by 朱少波 on 2020/4/17.
 */
public class RuleServer  {

    public static boolean  CheckRuleByModels(Connection  con,String RuleClassCode,  iRule... datas) throws SQLException {
        Map<String, Object> RuleData = new HashMap<String, Object>();
        for (iRule data : datas) {
            try {
                String ID =data.getRuleId();
                if (!RuleData.containsKey(ID)) RuleData.put(ID, data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return  CheckRuleByFormula(con,RuleData, RuleClassCode)==null;
    }


    public static String CheckRule(Connection  con,String RuleClassCode, iRule... datas) throws SQLException {

        Map<String, Object> RuleData = new HashMap<String, Object>();
        SetRuleId(RuleData, datas);
        return CheckRule(con,RuleClassCode,RuleData);
    }

    public static String CheckRule(Connection  con,String RuleClassCode, List<iRule> list, iRule... datas) throws SQLException {
        if(list==null || list.size()<=0) return  CheckRule(con,RuleClassCode,datas);

        for (iRule iRule : list) {
            Map<String, Object> RuleData = new HashMap<String, Object>();
            SetRuleId(RuleData, datas);

            String ID = iRule.getRuleId();
            if (!RuleData.containsKey(ID)) RuleData.put(ID, iRule);

            String result = CheckRule(con,RuleClassCode,RuleData);
            if(result!=null && !"".equals(result)) return result;
        }
        return "";
    }

    public static String CheckRule(Connection  con,String RuleClassCode, List<iRule> list) throws SQLException {
        if(list==null || list.size()<=0) return "";

        for (iRule iRule : list) {
            Map<String, Object> RuleData = new HashMap<String, Object>();

            RuleData.put( iRule.getRuleId(), iRule);
            String result = CheckRule(con,RuleClassCode,RuleData);
            if(result!=null && !"".equals(result)) return result;
        }
        return "";
    }

    public static String CheckRule(Connection  con,String RuleClassCode, Map<String, Object> datas) throws SQLException {
        TmsComRuleEntity rule = CheckRuleByFormula(con,datas, RuleClassCode);
        if (rule != null) {
            return "不满足" + rule.getRuleClassDesc() + ", 要求: " + rule.getRuleDesc();
        }
        return "";
    }


    private static void SetRuleId(Map<String, Object> ruleData, iRule[] datas) {
        for (iRule data : datas) {
            try {
                String ID = data.getRuleId();
                if (!ruleData.containsKey(ID)) ruleData.put(ID, data);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static String CheckRuleEachModels(Connection  con,String RuleClassCode, List<Object> datas) throws SQLException {
        for (int i = 0; i < datas.size(); i++) {
            for (int j = i+1; j < datas.size() ; j++) {
                Map<String, Object> RuleData = new HashMap<String, Object>();
                RuleData.put("current",datas.get(i));
                RuleData.put("other",datas.get(j));
                TmsComRuleEntity rule = CheckRuleByFormula(con,RuleData, RuleClassCode);
                if(rule!=null){
                    return  "不满足" + rule.getRuleClassDesc() + ", 要求: " + rule.getRuleDesc();
                }
            }
        }

        return "";
    }


    public  static TmsComRuleEntity CheckRuleByFormula(Connection  con,Map<String, Object> Data, String RuleClass) throws SQLException {


        String sql = CoreXmlSqlParsersFactory
                .getSql("TmsDemand.getRule");
        PreparedStatement ps = con.prepareStatement(sql);
        ps.setObject(1, RuleClass);
        ResultSet rs = ps.executeQuery();
        List<TmsComRuleEntity> Rules = EntityTool.getEntitysByRs(rs,
                TmsComRuleEntity.class);
        rs.close();
        ps.close();

        if(Rules==null) return null;

        for (TmsComRuleEntity rule : Rules
                ) {
            try {
                if (rule.getComputeFormula() == null) return null;

                Data.put("Value",rule.getRuleVal());

                String formula =String.valueOf(rule.getComputeFormula());
                //"new Date({TL.transportEndTime}).getTime()/(1000*60*60) - new Date({XX.transportStartTime}).getTime()/(1000*60*60) < {Value}";


                ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
                Compilable compilable = (Compilable) engine;

                Bindings bindings = engine.createBindings(); //Local级别的Binding
                CompiledScript JSFunction; //解析编译脚本函数
                JSFunction = compilable.compile(formula
                );

              //  Data.forEach((k,v)-> bindings.put(k,v));

                for(Map.Entry<String, Object> entry : Data.entrySet()){
                    bindings.put(entry.getKey(),entry.getValue() );
                }


                Object result = JSFunction.eval(bindings);
                
                
                
                if(! Boolean.parseBoolean(result.toString())) return rule;

            } catch (Exception ex) {
                return rule;
            }
        }
        return null;
    }


    /**
     * 根据属性，获取get方法
     *
     * @param ob   对象
     * @param name 属性名
     * @return
     * @throws Exception
     */
    public static Object getGetMethod(Object ob, String name) throws Exception {
        try {
            Method[] m = ob.getClass().getMethods();
            for (int i = 0; i < m.length; i++) {
                if (( "get" + name ).toLowerCase().equals(m[i].getName().toLowerCase())) {
                    return m[i].invoke(ob);
                }
            }

        }catch (Exception ex){
            return null;
        }
        return null;
    }
}
