package com.gyee.alarm.rule;

import com.gyee.alarm.init.CacheContext;
import com.gyee.alarm.model.vo.DeviceTypeValue;
import com.gyee.alarm.rule.expression.AlarmExpression;
import com.gyee.alarm.rule.expression.Analyzer;
import com.gyee.common.model.PointData;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
@NoArgsConstructor
@Slf4j
public class AlarmFunction {

    private DeviceTypeValue thingType;

    private String thingId;

    private AlarmExpression alarmExpression;

    private List<AlarmFunction> children;

    private AlarmFunction parent;

    //key: uniformcode
    private Map<String, PointData> tagMap;

  

    private long lastExplainTime = 0;

    private long getLatestTsDataTs() {
        long ts = 0;
        if (alarmExpression.getVarList() != null && alarmExpression.getVarList().size() > 0) {
            for (String varName : alarmExpression.getVarList()) {
                if (varName.startsWith(Analyzer.FUNCODE))
                    continue;
                PointData tagInfo = getTagInfo(varName);
                if (tagInfo != null && ts < tagInfo.getPointTime())
                    ts = tagInfo.getPointTime();
            }
        }
        if (children != null && children.size() > 0) {
            for (AlarmFunction child : children) {
                if (ts < child.getLatestTsDataTs())
                    ts = child.getLatestTsDataTs();
            }
        }
        return ts;
    }

    public Object explain() {
        long ts1 = getLatestTsDataTs();
        if (ts1 <= lastExplainTime) {
            return "c";
        } else {
            lastExplainTime = ts1;
        }

        Map<String, Object> varMap = new HashMap<>();
        if (alarmExpression.getVarList() != null && alarmExpression.getVarList().size() > 0) {
            for (String varName : alarmExpression.getVarList()) {
                if (varName.startsWith(Analyzer.FUNCODE))
                    continue;
                PointData tagInfo = getTagInfo(varName);
                if (tagInfo == null) {
                    log.warn("未找到标签点！ThingId=" + this.getThingId() + ", uc=" + varName + ",rule=" + alarmExpression.getRuleId());
                    continue;
                }
                double varValue = tagInfo.getPointValueInDouble();
                varMap.put(varName, varValue);

            }
        }

        if (children != null && children.size() > 0) {
            for (AlarmFunction af : children) {
                Object result = af.explain();
                varMap.put(af.getAlarmExpression().getFunCode(), result);
            }
        }

        return ScriptShell.parseExpr(alarmExpression.getExpression(), varMap);
    }

    public AlarmFunction(AlarmExpression aExpression, DeviceTypeValue tType, String tId) {
        thingType = tType;
        thingId = tId;
        alarmExpression = aExpression;
        children = new ArrayList<>();
        if (alarmExpression.getChildren() != null && alarmExpression.getChildren().size() > 0) {
            for (AlarmExpression subExp : alarmExpression.getChildren()) {
                AlarmFunction aFun = null;
                if (subExp.getFunType() != null && subExp.getFunType().equals("RiseExceed")) {
                    aFun = new AlarmFunctionRiseExceed(subExp, tType, tId);
                } else if (subExp.getFunType() != null && subExp.getFunType().equals("LastUpdateTime")) {
                    aFun = new AlarmFunctionLastUpdateTime(subExp, tType, tId);
                } else if (subExp.getFunType() != null && subExp.getFunType().equals("Sustain")) {
                    if (subExp.getExpression().startsWith("Sustain")) {
                        String exp = subExp.getExpression();
                        int offset = exp.lastIndexOf(',');
                        String exp2 = exp.substring(8, offset);
                        subExp.setExpression(exp2);
                        String parms = exp.substring(offset + 1, exp.length() - 1);
                        ArrayList<String> paramlist = new ArrayList<>();
                        paramlist.add(parms);
                        subExp.setFunParams(paramlist);
                    }
                    aFun = new AlarmFunctionSustain(subExp, tType, tId);
                }
                else if (subExp.getFunType() != null && subExp.getFunType().equals("MAX")) {
                    aFun = new AlarmFunctionMAX(subExp, tType, tId);
                }
                else if (subExp.getFunType() != null && subExp.getFunType().equals("MIN")) {
                    aFun = new AlarmFunctionMIN(subExp, tType, tId);
                }
                else if (subExp.getFunType() != null && subExp.getFunType().equals("AVG")) {
                    aFun = new AlarmFunctionAVG(subExp, tType, tId);
                }
                if (aFun == null) {
                    aFun = new AlarmFunction(subExp, tType, tId);
                }
                aFun.setParent(this);
                children.add(aFun);
            }
        }

    }

    protected PointData getTagInfo(String varName) {
        if (tagMap == null) {
            if (thingType == DeviceTypeValue.WT) {
                tagMap = CacheContext.wtDataValueMap.get(thingId);
            } else  if (thingType == DeviceTypeValue.WP) {
                tagMap =  CacheContext.wpDataValueMap.get(thingId);
            } else  if (thingType == DeviceTypeValue.BT) {
                tagMap =  CacheContext.wsDataValueMap.get(thingId);
            }
        }


        if(tagMap.containsKey(varName))
        {
            long time=tagMap.get(varName).getPointTime()*1000;
            tagMap.get(varName).setPointTime(time);
            return tagMap.get(varName);
        }else
        {
            return null;
        }



    }

}
