package com.yeejoin.amos.fas.business.action;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yeejoin.amos.component.rule.MethodParam;
import com.yeejoin.amos.component.rule.RuleActionBean;
import com.yeejoin.amos.component.rule.RuleMethod;
import com.yeejoin.amos.fas.business.action.el.ELEvaluationContext;
import com.yeejoin.amos.fas.business.action.model.ContingencyEvent;
import com.yeejoin.amos.fas.business.action.model.ContingencyRo;
import com.yeejoin.amos.fas.business.action.model.DeviceRo;
import com.yeejoin.amos.fas.business.action.mq.WebMqttComponent;
import com.yeejoin.amos.fas.business.action.result.ActionResult;
import com.yeejoin.amos.fas.business.action.result.SafteyPlanResult;
import com.yeejoin.amos.fas.business.action.result.message.AbstractActionResultMessage;
import com.yeejoin.amos.fas.business.action.util.ContingencyLogPublisher;
import com.yeejoin.amos.fas.business.dao.repository.IPlanDetailDao;
import com.yeejoin.amos.fas.business.dao.repository.IPlanOperationRecordDao;
import com.yeejoin.amos.fas.business.feign.IDutyModeServer;
import com.yeejoin.amos.fas.business.feign.RemoteSecurityService;
import com.yeejoin.amos.fas.business.service.impl.RuleRunigSnapshotServiceImpl;
import com.yeejoin.amos.fas.business.service.intfc.IContingencyInstance;
import com.yeejoin.amos.fas.business.service.intfc.IEquipmentService;
import com.yeejoin.amos.fas.business.service.intfc.IRiskSourceService;
import com.yeejoin.amos.fas.business.service.model.ContingencyDeviceStatus;
import com.yeejoin.amos.fas.business.service.model.ToipResponse;
import com.yeejoin.amos.fas.business.util.CacheFactory;
import com.yeejoin.amos.fas.business.util.CacheMap;
import com.yeejoin.amos.fas.business.vo.Toke;
import com.yeejoin.amos.fas.common.enums.ContingencyPlanStatusEnum;
import com.yeejoin.amos.fas.common.enums.PlanRecordStatusEnum;
import com.yeejoin.amos.fas.core.enums.NumberEnum;
import com.yeejoin.amos.fas.core.util.CommonResponse;
import com.yeejoin.amos.fas.core.util.DateUtil;
import com.yeejoin.amos.fas.dao.entity.ContingencyPlanInstance;
import com.yeejoin.amos.fas.dao.entity.Equipment;
import com.yeejoin.amos.fas.dao.entity.PlanDetail;
import com.yeejoin.amos.fas.dao.entity.PlanOperationRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.context.RequestContext;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//import com.yeejoin.amos.fas.business.service.intfc.FireStengthService;

@Component
@RuleActionBean(beanLabel = "动态预案" )
public class ContingencyAction implements CustomerAction {


    private static String PACKAGEURL = "com.yeejoin.amos.fas.business.action.result.message.";

    public static final Logger log = LoggerFactory.getLogger(ContingencyAction.class);

    @Autowired
    private WebMqttComponent webMqttComponent;

    @Value("${auto-sys.push.type}")
    private String pushType;
    @Value("${spring.application.name}")
    private String serviceName;

    @Value("${station.name}")
    private String stationName;

    @Autowired
    private IContingencyInstance iContingencyInstance;

//    @Autowired
//    private FireStengthService fireStrengthService;
    @Autowired
    private ContingencyLogPublisher contingencyLogPublisher;

    @Autowired
    private IRiskSourceService riskSourceService;

    @Autowired
    private IDutyModeServer dutyModeServer;

    @Autowired
    private IEquipmentService equipmentService;

    @Autowired
    private RedisTemplate redisTemplate;

    private static Map<String, String> OPERATE_RECORD_ID = new HashMap<>();

    private static Map<String, Map<String, String>> stringStringMap = new HashMap<>();
    static SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");

    public static ConcurrentHashMap<String, Map<String, Object>> pointCache = new  ConcurrentHashMap<>();


    private static CacheMap cacheMap = CacheFactory.newChacheMap();
    private static final String TOKE = "TOKE";
    @Autowired
    private RemoteSecurityService remoteSecurityService;

    @Autowired
    private IPlanDetailDao planDetailDao;
    @Autowired
    private IPlanOperationRecordDao planOperationRecordDao;
    //当值值班长（S1）、副值班长(S2)、值班员(A1,A2,A3)、白班值班员、保安人员、驻站消防队长(F1)
 /*   private static Map<String, String> positionMap = new HashMap<String, String>() {{
        put("S1", "S1");
        put("S2", "S2");
        put("A1", "A1");
        put("A2", "A2");
        put("A3", "A3");
        put("F1", "F1");
    }};
*/

    /**
     * 预案文件中值为和数据字典中的对应关系
     * 消防
     * F1  	消防队长  	fireLeader
     * F2..F6 	队员 		firePerson      规则配置中队员1...6：firePerson1...firePerson6
     * FD .... 司机 		fireDriver		 规则配置中司机 1..6：fireDriver1...fireDriver6
     * 运维
     * S1 		值班长 	dutyLeader
     * S2 		副值班长	deputyDutyLeader
     * B1..B6	 值班员 	dutyCivilian	规则配置中值班员1...6：dutyCivilian1...dutyCivilian6
     * A1...A6	 副值班员 	deputyDutyCivilian 规则配置中副值班员1...6：deputyDutyCivilian1...deputyDutyCivilian6
     */

    public Map<String, String> getStrengthMap(ContingencyRo contingencyRo) {
    	String batchNo = contingencyRo.getBatchNo();
    	String orgCode = contingencyRo.getEquipmentOrgCode();
        Map<String, String> returnMap = stringStringMap.get(contingencyRo.getBatchNo());
        if (CollectionUtils.isEmpty(returnMap)) {
            stringStringMap = new HashMap<>();
            returnMap = new HashMap<>();

            Date curDate = new Date();
            JSONObject param = new JSONObject();
            param.put("dutyDate", curDate);
            Toke toke = remoteSecurityService.getServerToken();
            CommonResponse commonResponse = dutyModeServer.dutyListByDate(toke.getAppKey(), toke.getProduct(), toke.getToke(), orgCode, param.toJSONString());

//            String result = HttpUtil.appendPostJson("duty/dutyListByDate", param.toJSONString());
//            JSONObject jsonObject = JSONObject.parseObject(result);
//            JSONArray dataList = JSONObject.parseObject(commonResponse.getDataList().toString());


            String JSONStr = JSON.toJSONString(commonResponse.getDataList());
            JSONArray dataList = JSONObject.parseArray(JSONStr);
            log.info(String.format("请求值班系统返回dataList：%s", dataList));

            if (!ObjectUtils.isEmpty(dataList)) {
                Map<String, String> finalReturnMap = returnMap;
                dataList.forEach(
                        x -> {
                            JSONObject obj = (JSONObject) x;
                            String name = obj.getString("position");
                            finalReturnMap.put(name, obj.getString("dutyName"));
                        }
                );
            }
            stringStringMap.put(batchNo, returnMap);
        }
        log.info(String.format("returnMap:【 %s 】", returnMap));
        return returnMap;
    }

    /**
     * @param stepCode     当前步骤编号
     * @param stepName     当前步骤名称
     * @param nextStepCode 下一步编号
     * @param nextStepName 下一步名称
     * @param paramObj     预案对象
     */
    @RuleMethod(methodLabel = "步骤更新(新)", project = "换流站消防专项预案")
    public void stepInfoNew(@MethodParam(paramLabel = "当前步骤编号") String stepCode,
                            @MethodParam(paramLabel = "当前步骤名称") String stepName,
    		                @MethodParam(paramLabel = "下一步编号") String nextStepCode,
                            @MethodParam(paramLabel = "下一步名称") String nextStepName,
                         @MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        ArrayList list = new ArrayList();
        HashMap step = new HashMap();

        step.put("stepCode", stepCode);
        step.put("stepName", stepName);

        HashMap nextmap = new HashMap();
        nextmap.put("stepCode", nextStepCode);
        nextmap.put("stepName", nextStepName);
        list.add(step);
        list.add(nextmap);

        tempmap1.put("step", list);
        tempmap1.put("preStep", new HashMap());
        result.add(tempmap1);
        log.info("步骤更新(new)" + JSONObject.toJSONString(result));
        this.sendcmd("steparea", contingencyRo, result);
    }

    /**
     * @param stepCode     当前步骤编号
     * @param paramObj     预案对象
     */
    @RuleMethod(methodLabel = "步骤更新", project = "换流站消防专项预案")
    public void stepInfo(@MethodParam(paramLabel = "当前编号") String stepCode,
    		@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
//        Map<String, Object> tempmap1 = new HashMap<>();
//        SetpEnum[] stepArr = SetpEnum.values();
//        ArrayList list = new ArrayList();
//        HashMap preStep = new HashMap();
//        StepComparator comparator = new StepComparator();
//        Arrays.sort(stepArr, comparator);
//
//        boolean flage = false;
//        SetpEnum pstep = null;
//        for (SetpEnum step : stepArr) {
//        	if (Long.valueOf(step.getValue()) == Long.valueOf(stepCode)) {
//        		if (!ObjectUtils.isEmpty(pstep)) {
//        			preStep.put("stepCode", pstep.getValue());
//            		preStep.put("stepName", pstep.getTitle());
//        		}
//        		flage = true;
//        	}
//        	if (flage) {
//        		HashMap map = new HashMap();
//        		map.put("stepCode", step.getValue());
//        		map.put("stepName", step.getTitle());
//        		list.add(map);
//        	}
//        	pstep = step;
//        }
//
//        tempmap1.put("step", list);
//        tempmap1.put("preStep", preStep);
//        result.add(tempmap1);
//        log.info("巡检消息发送规则" + JSONObject.toJSONString(result));
        this.sendcmd("steparea", contingencyRo, result);
    }




    public void sendcmd(String msgType, Object contingency, SafteyPlanResult result) {
        ContingencyRo ro = (ContingencyRo)contingency;
        ro.setTelemetryMap(null);
        ro.setTelesignallingMap(null);
        Constructor<?> constructor;
        try {
            constructor = Class.forName(
                    PACKAGEURL + result.getClass().getSimpleName() + "Message")
                    .getConstructor(ActionResult.class);
            AbstractActionResultMessage<?> action = (AbstractActionResultMessage<?>) constructor.newInstance(result);
            if ("mqtt".equals(pushType.toLowerCase())) {
                ToipResponse toipResponse = action.buildResponse(msgType, contingency, result.toJson());
                String topic = String.format("/%s/%s/%s", serviceName, stationName,"plan");
                log.info(String.format("mqtt[%s]:【 %s 】", topic, toipResponse.toJsonStr()));
                webMqttComponent.publish(topic, toipResponse.toJsonStr());

                ContingencyEvent event = new ContingencyEvent(this);
                event.setMsgBody(toipResponse.toJsonStr());
                event.setTopic(topic);
                event.setMsgType(msgType);
                event.setContingency(contingency);
                contingencyLogPublisher.publish(event);
            } else if ("websocket".equals(pushType.toLowerCase())){
                action.execute(msgType, contingency);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void sendweb(String msgType, Object contingency, SafteyPlanResult result) {
        ContingencyRo ro = (ContingencyRo)contingency;
        ro.setTelemetryMap(null);
        ro.setTelesignallingMap(null);
        Constructor<?> constructor;
        try {
            constructor = Class.forName(
                    PACKAGEURL + result.getClass().getSimpleName() + "Message")
                    .getConstructor(ActionResult.class);
            AbstractActionResultMessage<?> action = (AbstractActionResultMessage<?>) constructor.newInstance(result);
            ToipResponse toipResponse = action.buildResponse(msgType, contingency, result.toJson());
            String topic = String.format("/%s/%s/%s", serviceName, stationName,"numberPlan");
            log.info(String.format("mqtt[%s]:【 %s 】", topic, toipResponse.toJsonStr()));
            webMqttComponent.publish(topic, toipResponse.toJsonStr());
            ContingencyEvent event = new ContingencyEvent(this);
            event.setMsgBody(toipResponse.toJsonStr());
            event.setTopic(topic);
            event.setMsgType(msgType);
            event.setContingency(contingency);
            contingencyLogPublisher.publish(event);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * @param stepCode 当前步骤编号
     * @param paramObj 预案对象
     */
    @RuleMethod(methodLabel = "步骤更新保存", project = "换流站消防专项预案")
    public void saveStepInfo(@MethodParam(paramLabel = "当前编号") String stepCode, @MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        iContingencyInstance.updateStep(stepCode, contingencyRo.getBatchNo());
    }


    /**
     * @param content  消息内容
     * @param paramObj 预案对象
     */
    @RuleMethod(methodLabel = "执行记录", project = "换流站消防专项预案")
    public void messageRecord(@MethodParam(paramLabel = "消息内容") String content, @MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);
        //转换content中的变量
        content = instedParams(content, contingencyRo);
        iContingencyInstance.createInstanceRecord(contingencyRo.getBatchNo(), "", "DEFAULT", content, "MESSAGE", "");

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        try {
        	SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        	List<ContingencyPlanInstance> list = iContingencyInstance.queryForTimeLine(contingencyRo.getBatchNo(), "MESSAGE");
        	ArrayList records = new ArrayList<>();
        	if (!ObjectUtils.isEmpty(list)) {
        		list.forEach(action -> {
        			HashMap map = new HashMap();
            		map.put("time", sdf1.format(action.getCreateDate().getTime()));
            		map.put("stepName", action.getContent());
            		records.add(map);
            	});
        	}
			tempmap1.put("content", records);
            tempmap1.put("status",PlanRecordStatusEnum.OPERATION.getCode());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        result.add(tempmap1);
        System.out.println("--------------------messageRecord----------------------"+result);
        this.sendcmd("recordarea", paramObj, result);
        this.sendweb("recordarea", paramObj, result);
    }

    /**
     * <pre>
     * 智能辅助
     * </pre>
     *
     * @param step     当前步骤
     * @param icon     图标
     * @param title    标题
     * @param image    图片集合
     * @param table    表格
     * @param content  内容
     * @param paramObj 预案对象
     */
    @RuleMethod(methodLabel = "智能辅助", project = "换流站消防专项预案")
    public void help(@MethodParam(paramLabel = "当前步骤") String step,
    		@MethodParam(paramLabel = "图标")String icon,
    		@MethodParam(paramLabel = "标题")String title,
    		@MethodParam(paramLabel = "图片集") String image,
    		@MethodParam(paramLabel = "表格数据") String table,
    		@MethodParam(paramLabel = "文本内容") String content,
    		@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        //转换智能辅助中的变量
        content = instedParams(content, contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("icon", icon);
        tempmap1.put("step", step);
        tempmap1.put("title", title);
        tempmap1.put("content", content);
        tempmap1.put("image", image);
        tempmap1.put("table", table);
//        tempmap1.put("batchNo", contingencyRo.getBatchNo());
//        tempmap1.put("contingencyRo", contingencyRo);
        result.add(tempmap1);

        this.sendcmd("helparea", paramObj, result);
    }


    private String instedParams(String content, ContingencyRo contingencyRo) {

        Map<String, String> strengthMap = this.getStrengthMap(contingencyRo);
        for (String key : strengthMap.keySet())
            content = content.replaceAll("\\$\\{" + key + "}", strengthMap.get(key));

	        Field[] fields = contingencyRo.getClass().getDeclaredFields();
	        Method getMethod = null;
	        try {
	            for (Field field : fields) {
	                if (field.getName().equals("serialVersionUID"))
	                    continue;
	                String fileNameInMethod = String.valueOf(field.getName().charAt(0)).toUpperCase() + field.getName().substring(1);
	                getMethod = contingencyRo.getClass().getMethod("get" + fileNameInMethod);
	                String value = String.valueOf(getMethod.invoke(contingencyRo));
	                content = content.replaceAll("\\$\\{" + field.getName() + "}", value);
	            }

	            content = getNative(content);
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
        return content;
    }

    public String getNative(String str)
	{
		Pattern p = Pattern.compile("\\$\\{(.*?)\\}");
		Matcher m = p.matcher(str);
		while (m.find())
		{
			String parameter = m.group();

			Object parametervalue = ELEvaluationContext
					.getValue(parameter.substring(1, parameter.length() - 1));
			if(parametervalue != null)
				str = str.replace(parameter,
					parametervalue != null ? parametervalue.toString() : null);
		}
		return str;
	}

    /**
     * 交互动作
     *
     * @param actionName 动作名称
     * @param icon       图标
     * @param tips       提示信息
     * @param buttonJson 按钮json字符串
     * @param paramObj   预案对象
     */
    @RuleMethod(methodLabel = "交互动作", project = "换流站消防专项预案")
    public void operation(@MethodParam(paramLabel = "动作名称") String actionName,
    		@MethodParam(paramLabel = "图标") String icon,
    		@MethodParam(paramLabel = "提示信息") String tips,
    		@MethodParam(paramLabel = "按钮json字符串") String buttonJson,
    		@MethodParam(paramLabel = "预案对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        //转换content中的变量
        tips = instedParams(tips, contingencyRo);


        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();


        String contingencyPlanId = getContingencyPlanId(contingencyRo.getBatchNo(), actionName, icon, tips, buttonJson);

        tempmap1.put("actionName", actionName);
        tempmap1.put("icon", icon);
        tempmap1.put("tips", tips);
        tempmap1.put("button", buttonJson);
        tempmap1.put("caseId", contingencyPlanId);
        result.add(tempmap1);

        this.sendcmd("optionarea", paramObj, result);

    }


    private boolean sendButton(String batchNo, String contingencyPlanId, String equipmentId, String actionName, String buttonJson) {


        ObjectMapper objectMapper = new ObjectMapper();

        /**
         * batchNo
         * stepCode
         * buttonCode
         * confirm
         * contingencyPlanId
         * stepState
         */

        try {
            Map button = objectMapper.readValue(buttonJson, Map.class);
            Map operateInstance = (Map) ((List) button.get("operate")).get(0);
            ContingencyDeviceStatus contingencyDeviceStatus = new ContingencyDeviceStatus();
            contingencyDeviceStatus.setActionName(actionName);
            contingencyDeviceStatus.setButtonCode(String.valueOf(operateInstance.get("code")));
            contingencyDeviceStatus.setConfirm("CONFIRM");
            contingencyDeviceStatus.setContingencyPlanId(contingencyPlanId);
            contingencyDeviceStatus.setEquipmentId(equipmentId);
            contingencyDeviceStatus.setStepCode(String.valueOf(button.get("stepCode")));
            contingencyDeviceStatus.setStepState(String.valueOf(operateInstance.get("stepState")));
            riskSourceService.queryContingencyDeviceStatus(contingencyDeviceStatus);

        } catch (IOException e) {
            e.printStackTrace();
        }

        return false;
    }


    /**
     * 保存交互动作
     *
     * @param actionName 动作名称
     * @param icon       图标
     * @param tips       提示信息
     * @param buttonJson 按钮json字符串
     * @param paramObj   预案对象
     */
    @RuleMethod(methodLabel = "保存交互动作", project = "换流站消防专项预案")
    public void saveOperation(@MethodParam(paramLabel = "动作名称") String actionName,
    		@MethodParam(paramLabel = "图标") String icon,
    		@MethodParam(paramLabel = "提示信息") String tips,
    		@MethodParam(paramLabel = "按钮json字符串") String buttonJson,
    		@MethodParam(paramLabel = "对象") Object paramObj) {

        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        //转换content中的变量
        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        try {
        	SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        	List<ContingencyPlanInstance> list = iContingencyInstance.queryForTimeLine(contingencyRo.getBatchNo(), "MESSAGE");
        	ArrayList records = new ArrayList<>();
        	if (!ObjectUtils.isEmpty(list)) {
        		list.forEach(action -> {
        			HashMap map = new HashMap();
//            		map.put("time", sdf.format(action.getCreateDate()));
                    map.put("time", sdf1.format(action.getCreateDate().getTime()));
            		map.put("stepName", action.getContent());
            		records.add(map);
            	});
        	}
			tempmap1.put("content", records);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        result.add(tempmap1);
        System.out.println("--------------------saveOperation----------------------"+result);
        this.sendcmd("recordarea", paramObj, result);
    }

    private String getContingencyPlanId(String batchNo, String actionName, String icon, String tips, String buttonJson) {
        String cacheKey = batchNo + actionName;
        String contingencyPlanId = null;
        ContingencyPlanInstance contingencyPlanInstance = null;
        if (OPERATE_RECORD_ID.get(cacheKey) == null) {
            contingencyPlanInstance = iContingencyInstance.createInstanceRecord(batchNo, actionName, "DEFAULT", buttonJson, "OPERATE", icon);
            contingencyPlanId = contingencyPlanInstance.getId();
            OPERATE_RECORD_ID.put(cacheKey, contingencyPlanId);
        } else {
            contingencyPlanId = OPERATE_RECORD_ID.get(cacheKey);
            OPERATE_RECORD_ID.remove(cacheKey);
        }
        return contingencyPlanId;
    }


    /**
     * 	地图动作推送
     *
     * @param actionName 动作名称标识
     * @param paramObj   预案对象
     */
    @RuleMethod(methodLabel = "地图动作", project = "换流站消防专项预案")
    public void mapAction(@MethodParam(paramLabel = "动作名称标识") String actionName, @MethodParam(paramLabel = "参数")  String paramJSON, @MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;

        log.error("=======================================================================================");
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("key", actionName);
        tempmap1.put("content",paramJSON);
        result.add(tempmap1);
        this.sendcmd("maparea", paramObj, result);
    }

    @RuleMethod(methodLabel = "地图动画", project = "换流站消防专项预案")
    public void mapCartoonAction(
    		@MethodParam(paramLabel = "动作名称标识") String actionName,
    		@MethodParam(paramLabel = "动作类型")  String actionType,
    		@MethodParam(paramLabel = "动作类型参数") String paramJSON,
    		@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;

        log.error("=======================================================================================");
        stopSnapshop(contingencyRo);
        String parameter = instedParams(paramJSON, contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("key", actionName);
        tempmap1.put("content",actionType);
        tempmap1.put("parameter",parameter);
        result.add(tempmap1);
        this.sendcmd("maparea", paramObj, result);
    }

    /**
     * 顶部消息提示
     *
     * @param content     消息内容
     * @param messageType 消息类型 messageType 黑色框消息类型CONTINGENCY,，滚动消息：CURRENTMESSAGE
     * @param paramObj    预案对象
     */
    @RuleMethod(methodLabel = "消息提示", project = "换流站消防专项预案")
    public void topMessage(
    		@MethodParam(paramLabel = "标题") String title,
    		@MethodParam(paramLabel = "内容") String content,
    		@MethodParam(paramLabel = "图标") String icon,
    		@MethodParam(paramLabel = "类型") String messageType,
    		@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        //转换content中的变量
        content = instedParams(content, contingencyRo);

        tempmap1.put("content", content);
        tempmap1.put("type", messageType);//消息类型 messageType 黑色框消息类型 CONTINGENCY,，滚动消息：CURRENTMESSAGE
        tempmap1.put("title", title);
        tempmap1.put("icon", icon);
        result.add(tempmap1);

        this.sendcmd("message", paramObj, result);
    }

    /**
     * 启动预案
     *
     * @param paramObj    预案对象
     */
    @RuleMethod(methodLabel = "启动预案", project = "换流站消防专项预案")
    public void startPlan(@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("type", "event");
        tempmap1.put("content", "startPlan");
        result.add(tempmap1);

        this.sendcmd("message", paramObj, result);

        redisTemplate.opsForValue().set("contingencyRo", contingencyRo);
    }


    /**
     * 启动预案
     *
     * @param paramObj    预案对象
     */
    @RuleMethod(methodLabel = "结束预案", project = "换流站消防专项预案")
    public void stopPlan(@MethodParam(paramLabel = "对象") Object paramObj) {
        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        stopSnapshop(contingencyRo);

        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("type", "event");
        tempmap1.put("content", "stopPlan");
        //数字预案结束状态
        tempmap1.put("status",PlanRecordStatusEnum.COMPLETE.getCode());
        result.add(tempmap1);

        this.sendcmd("message", paramObj, result);
        redisTemplate.delete("contingencyRo");

        //  结束预案，更新设备重点设备参数
        if (contingencyRo != null) {
            Equipment equipment = equipmentService.queryOne(Long.parseLong(contingencyRo.getEquipmentId()));
            if (equipment != null) {
                equipment.setEndTime(DateUtil.getDateNow());
                equipment.setReserveSource(NumberEnum.ZERO.getValue());
                equipment.setStatus(NumberEnum.ZERO.getValue());
                equipmentService.save(equipment);
            }
        }

        //  结束预案 更新预案记录表,预案状态
        PlanOperationRecord planOperationRecord = planOperationRecordDao.findByBatchNo(contingencyRo.getBatchNo());
        if(planOperationRecord!=null && planOperationRecord.getStatus()==PlanRecordStatusEnum.OPERATION.getCode()){
            planOperationRecord.setStatus(PlanRecordStatusEnum.COMPLETE.getCode());
            planOperationRecord.setEndTime(new Date());
            planOperationRecordDao.save(planOperationRecord);
            Optional<PlanDetail>  optionalPlanDetail = planDetailDao.findById(planOperationRecord.getPlanId());
            if(optionalPlanDetail.get()!=null){
                PlanDetail planDetail = optionalPlanDetail.get();
                planDetail.setStatus(ContingencyPlanStatusEnum.AVAILABLE.getCode());
                planDetailDao.save(planDetail);
            }
            //数字预案业务屏web端发送消息
            this.sendweb("recordarea", paramObj, result);
        }

    }


    @RuleMethod(methodLabel = "自动执行步骤", project = "换流站消防专项预案")
    public void autoExecute(
    		@MethodParam(paramLabel = "动作名称") String actionName,
    		@MethodParam(paramLabel = "步骤编号") String stepCode,
    		@MethodParam(paramLabel = "按钮编码") String buttonCode,
    		@MethodParam(paramLabel = "步骤状态") String stepState,
    		@MethodParam(paramLabel = "预案对象") Object paramObj) {
    	ContingencyRo contingencyRo = (ContingencyRo) paramObj;
    	ContingencyPlanInstance contingencyPlanInstance = iContingencyInstance.createInstanceRecord(contingencyRo.getBatchNo(), actionName, "DEFAULT", "", "OPERATE", "");

    	Toke toke = remoteSecurityService.getServerToken();
    	RequestContext.setToken(toke.getToke());
        RequestContext.setProduct(toke.getProduct());
        try {
			iContingencyInstance.setButtonExecuted(contingencyRo.getBatchNo(),contingencyPlanInstance.getId(),buttonCode,"CONFIRM");
			iContingencyInstance.fire(contingencyRo.getBatchNo(),stepCode, contingencyPlanInstance.getId(),buttonCode, "CONFIRM", stepState);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }

    @RuleMethod(methodLabel = "添加步骤执行", project = "换流站消防专项预案")
    public void addExecute(
    		@MethodParam(paramLabel = "步骤编号") String stepCode,
    		@MethodParam(paramLabel = "按钮编码") String buttonCode,
    		@MethodParam(paramLabel = "设备数据") Object paramObj) {
    	SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        Map<String, Object> content = new HashMap<>();

        content.put("stepCode", stepCode);
        content.put("buttonCode", buttonCode);

        DeviceRo ro = (DeviceRo)paramObj;
        Map<String, Object> equipemtnPoints = pointCache.get(ro.getEquipmentId());
        if (ObjectUtils.isEmpty(equipemtnPoints)) {
        	equipemtnPoints = new HashMap<>();
        }
        equipemtnPoints.put(stepCode+"-"+buttonCode, content);
        tempmap1.put("type", "buttonCache");
        tempmap1.put("content", equipemtnPoints.values());
        result.add(tempmap1);
        this.sendcmd("message", ro, result);
    }

    @RuleMethod(methodLabel = "清除步骤执行", project = "换流站消防专项预案")
    public void clearExecute(
    		@MethodParam(paramLabel = "步骤编号") String stepCode,
    		@MethodParam(paramLabel = "按钮编码") String buttonCode,
    		@MethodParam(paramLabel = "设备数据") Object paramObj) {
    	SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();
        Map<String, Object> content = new HashMap<>();

        content.put("stepCode", stepCode);
        content.put("buttonCode", buttonCode);

        DeviceRo ro = (DeviceRo)paramObj;
        Map<String, Object> equipemtnPoints = pointCache.get(ro.getEquipmentId());
        if (!ObjectUtils.isEmpty(equipemtnPoints)) {
        	equipemtnPoints.remove(stepCode+"-"+buttonCode);
        }

        tempmap1.put("type", "buttonCache");
        if (!ObjectUtils.isEmpty(equipemtnPoints)) {
        	tempmap1.put("content", equipemtnPoints.values());
        } else {
        	tempmap1.put("content", new ArrayList());
        }
        result.add(tempmap1);

        this.sendcmd("message", ro, result);
    }

    @RuleMethod(methodLabel = "同步自动执行步骤", project = "换流站消防专项预案")
    public void sendExecute(@MethodParam(paramLabel = "预案对象") Object paramObj) {
    	SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        ContingencyRo contingencyRo = (ContingencyRo) paramObj;
        Map<String, Object> equipemtnPoints = pointCache.get(contingencyRo.getEquipmentId());

        tempmap1.put("type", "buttonCache");
        tempmap1.put("content", ObjectUtils.isEmpty(equipemtnPoints) ? new ArrayList<>() : equipemtnPoints.values());
        result.add(tempmap1);

        this.sendcmd("message", paramObj, result);
    }

    public void sendcmd(String msgType, DeviceRo deviceRo, SafteyPlanResult result) {
        Constructor<?> constructor;
        try {
            constructor = Class.forName(
                    PACKAGEURL + result.getClass().getSimpleName() + "Message")
                    .getConstructor(ActionResult.class);
            AbstractActionResultMessage<?> action = (AbstractActionResultMessage<?>) constructor.newInstance(result);
            if ("mqtt".equals(pushType.toLowerCase())) {
            	ToipResponse toipResponse = action.buildResponse(msgType, deviceRo, result.toJson());
            	String topic = String.format("/%s/%s/%s", serviceName, stationName,"plan");
            	log.info(String.format("mqtt[%s]:【 %s 】", topic, toipResponse.toJsonStr()));
                webMqttComponent.publish(topic, toipResponse.toJsonStr());

                ContingencyEvent event = new ContingencyEvent(this);
                event.setMsgBody(toipResponse.toJsonStr());
                event.setTopic(topic);
                event.setMsgType(msgType);
                event.setContingency(deviceRo);
                contingencyLogPublisher.publish(event);
            } else if ("websocket".equals(pushType.toLowerCase())){
            	action.execute(msgType, deviceRo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void stopSnapshop(ContingencyRo contingencyRo) {
        if (RuleRunigSnapshotServiceImpl.getReplayBatchNo() != null && !RuleRunigSnapshotServiceImpl.getReplayBatchNo().equals(contingencyRo.getBatchNo()))
            RuleRunigSnapshotServiceImpl.setReplayBatchNoToNull();
    }

    @Override
    public void intreeuptPlan(String batchNo) {
        ContingencyRo contingencyRo = new ContingencyRo();
        contingencyRo.setBatchNo(batchNo);
        SafteyPlanResult result = new SafteyPlanResult();
        Map<String, Object> tempmap1 = new HashMap<>();

        tempmap1.put("type", "event");
        ArrayList records = new ArrayList<>();
        HashMap map = new HashMap();
        map.put("time", sdf.format(new Date()));
        map.put("stepName","应急处置中断");
        records.add(map);
        tempmap1.put("content", records);
        //数字预案结束状态
        tempmap1.put("status",PlanRecordStatusEnum.INTERRUPT.getCode());
        result.add(tempmap1);
        //数字预案业务屏web端发送消息
        this.sendweb("recordarea", contingencyRo, result);
        updateNumberPlan(contingencyRo.getBatchNo());
    }

    /**
     * 修改数字预案状态
     * */
   public void updateNumberPlan(String batchNo){
        //  结束预案 更新预案记录表,预案状态
        PlanOperationRecord planOperationRecord = planOperationRecordDao.findByBatchNo(batchNo);
        if(planOperationRecord!=null){
            planOperationRecord.setStatus(PlanRecordStatusEnum.INTERRUPT.getCode());
            planOperationRecord.setEndTime(new Date());
            planOperationRecordDao.save(planOperationRecord);
            Optional<PlanDetail>  optionalPlanDetail = planDetailDao.findById(planOperationRecord.getPlanId());
            if(optionalPlanDetail.get()!=null){
                PlanDetail planDetail = optionalPlanDetail.get();
                planDetail.setStatus(ContingencyPlanStatusEnum.AVAILABLE.getCode());
                planDetailDao.save(planDetail);
            }
        }
    }
}
