package com.zd.laboratory.mqtt.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.Assert;
import com.zd.common.core.utils.SpringUtils;
import com.zd.laboratory.domain.LabHardware;
import com.zd.laboratory.event.LabMessageEvent;
import com.zd.laboratory.mqtt.config.MqttConfig;
import com.zd.laboratory.mqtt.constants.MqttConstants;
import com.zd.laboratory.mqtt.entiy.EquipmentStatus;
import com.zd.laboratory.mqtt.entiy.MessageBody;
import com.zd.laboratory.mqtt.entiy.SensorStatus;
import com.zd.laboratory.mqtt.entiy.SubHardwareStatus;
import com.zd.laboratory.mqtt.enums.BigViewDataType;
import com.zd.laboratory.mqtt.enums.SendMode;
import com.zd.system.api.laboratory.domain.vo.SubFunction;
import com.zd.system.api.speak.RemoteSpeakService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 实验室消息发送管理 -- 对外使用该类进行操作
 *
 * @Author: zhoupan
 * @Date: 2021/10/08/11:03
 * @Description:
 */
@Service
public class SubMessageSendManager {

    private static Logger logger = LoggerFactory.getLogger(SubMessageSendManager.class);

    @Autowired
    CommonSend commonSend;

    @Autowired
    public MqttConfig mqttConfig;

    @Autowired
    private RemoteSpeakService remoteSpeakService;

    /**
     * 发送疏散线路通知
     *
     * @param exitLineNotic
     */
    public void SendExitLineUpdate(Map exitLineNotic) {

        Assert.isNotNull(exitLineNotic, "发送疏散线路通知不能为空");
        MessageBody messageBody = new MessageBody();
        messageBody.setData(exitLineNotic);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_EXIT_LINE, messageBody, SendMode.ONCE);
    }

    /**
     * 发送大屏数据更新通知
     *
     * @param bigViewDataType
     */
    public void SendBigViewUpdate(BigViewDataType bigViewDataType) {

        Assert.isNotNull(bigViewDataType, "发送大屏更新数据类型不能为空");
        MessageBody messageBody = new MessageBody();
        messageBody.setData(bigViewDataType);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_BIG_VIEW, messageBody, SendMode.ONCE);
    }

    /**
     * 发送一体机预警测点
     *
     * @param id 实验室ID
     */
    public void sendWranFunctionToSub(Long id, MessageBody messageBody) {


        if (id == null) return;

        //仅发送一次
        commonSend.send(MqttConstants.LAB_BIG_VIEW, messageBody, SendMode.ONCE);
    }

    /**
     * 发送测点数据 到对应实验室测点数据主题
     *
     * @param subId
     * @param subFunction
     */
    public void sendFunctionUpdate(Long subId, SubFunction subFunction) {
        if (subId == null) return;
        MessageBody messageBody = getMessageBody(subFunction);
        //仅发送一次
        commonSend.send(getFunctionSubTopic(subId), messageBody, SendMode.ONCE);
    }

    /**
     * 发送硬件状态数据，同时发送到实验室
     *
     * @param hardware
     * @param equipmentStatus
     * @param type            协议类型 1 继电器 2 视频监控
     */
    public void sendHardwareUpdate(LabHardware hardware, List<EquipmentStatus> equipmentStatus, int type) {
        MessageBody messageBody = getMessageBody(equipmentStatus);
        //如果实验室ID为null则不发送实验室主题
        if (hardware.getSubjectId() != null) {
            SubHardwareStatus subHardwareStatus = new SubHardwareStatus();
            subHardwareStatus.setSubId(hardware.getSubjectId());
            subHardwareStatus.setEquipmentStatus(equipmentStatus);
            String topic = MqttConstants.LAB_VIDEO_DATA + hardware.getSubjectId();
            //发送实验室主题
            commonSend.send(topic, messageBody, SendMode.ONCE);
            //发送以实验室为主体数据
            if (type == 1) {
                commonSend.send(MqttConstants.LAB_HARDWARE_DATA_SUB, getMessageBody(subHardwareStatus), SendMode.ONCE);
            } else {
                commonSend.send(MqttConstants.LAB_VIDEO, getMessageBody(subHardwareStatus), SendMode.ONCE);
            }
        }
        //仅发送一次
        commonSend.send(MqttConstants.LAB_VIDEO_DATA, messageBody, SendMode.ONCE);
    }


    /**
     * 发送硬件状态数据，同时发送到实验室
     * @param equipmentStatus
     */
    public void sendNewHardwareUpdate(List<EquipmentStatus> equipmentStatus) {
        MessageBody messageBody = getMessageBody(equipmentStatus);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_VIDEO_DATA, messageBody, SendMode.ONCE);
    }

    /**
     * 发送硬件状态数据，同时发送到一体机实验室
     * @param equipmentStatus
     */
    public void sendMachineNewHardwareUpdate(List<EquipmentStatus> equipmentStatus,Long subjectId) {
        if(null!=subjectId){
            MessageBody messageBody = getMessageBody(equipmentStatus);
            //仅发送一次
            commonSend.send(MqttConstants.LAB_VIDEO_DATA+subjectId, messageBody, SendMode.ONCE);
        }
    }


    private MessageBody getMessageBody(Object o) {

        MessageBody messageBody = new MessageBody();
        messageBody.setData(o);
        return messageBody;
    }

    /**
     * 发送测点数据 到对应实验室测点数据主题
     *
     * @param subFunction
     */
    public void sendFunctionUpdate(SubFunction subFunction) {
        sendFunctionUpdate(subFunction.getSubId(), subFunction);

    }

    /**
     * 发送所有实验室测点数据-到实验室公共主题
     *
     * @param subFunction
     */
    public void sendFunctionUpdateToCommon(SubFunction subFunction) {
        if (subFunction == null) return;
        String json = JSONObject.toJSONString(subFunction);
        logger.error("@@@@@@@@" + json);
        //发送事件
        //本来使用mqtt接收，因为mqtt 每个客户端接受到都会处理，
        List<LabMessageEvent> labMessageEvents = mqttConfig.getLabMessMap().get(MqttConstants.LAB_FUNCTION_DATA);
        if (CollUtil.isNotEmpty(labMessageEvents)) {
            labMessageEvents.forEach(a -> {
                SpringUtils.getApplicationContext().publishEvent(a.getNewLabMessageEvent(subFunction));
            });
        }
        MessageBody messageBody = new MessageBody();
        messageBody.setData(subFunction);
        //同时发送到对应实验室
        sendFunctionUpdate(subFunction);
        commonSend.send(MqttConstants.LAB_FUNCTION_DATA, messageBody, SendMode.ONCE);
    }

    /**
     * 发送预警数据-到单独实验室
     *
     * @param id
     */
    public void sendWranFunctionToSub(Long id) {
        if (id == null) {
            return;
        }
        MessageBody messageBody = new MessageBody();
        messageBody.setData(BigViewDataType.SUB_WRAN);
        commonSend.send(MqttConstants.LAB_WRAN + id, messageBody, SendMode.ONCE);
    }

    /**
     * 通知一体机logo查询
     *
     */
    public void noticeFunctionToOneMachine() {
        MessageBody messageBody = new MessageBody();
        messageBody.setData(BigViewDataType.NOTICE_ONEPC_LOGO);
        commonSend.send(MqttConstants.SYS_LOGO_CONFIG, messageBody, SendMode.ONCE);
    }

    /**
     * 获取实验室测点主题
     *
     * @param subId
     * @return
     */
    private String getFunctionSubTopic(Long subId) {
        return Optional.ofNullable(subId).map(a -> MqttConstants.LAB_FUNCTION_DATA + subId).orElseThrow(() -> new ServiceException("实验室ID不能为空"));

    }

    /**
     * 发送一体机通知消息
     *
     * @param subId 实验室id,context 发送内容
     */
    public void sendOnepcSubNews(Long subId,Integer type,String context) {
        if (subId == null) return;
        //音频播放
        if(type==2){
            context=remoteSpeakService.textParseUrl(50,80,context);
            JSONObject jsonObject=JSONObject.parseObject(context);
            context=jsonObject.getString("url");
            context=context.replace("http://180.76.134.43:10010/","http://192.168.8.101:10008/");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("context",context);
        map.put("type",type);
        MessageBody messageBody = new MessageBody();
        messageBody.setData(map);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_ONEPC_SUB_NEWS + subId, messageBody, SendMode.ONCE);
    }

    /**
     * 发送一体机通知apk升级
     *
     * @param object 一体机json字符串
     */
    public void sendOnepcApkup(JSONObject object) {
        if (object == null || "".equals(object)) return;
        MessageBody messageBody = new MessageBody();
        messageBody.setData(object);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_ONEPC_SUB_APKUP + object.get("onepcHardwareNum"), messageBody, SendMode.ONCE);
    }


    /**
     * 发送一体机通知配置变更
     *
     * @param object 一体机json字符串
     */
    public void sendOnepcUpConfig(JSONObject object) {
        if (object == null || "".equals(object)) return;
        MessageBody messageBody = new MessageBody();
        messageBody.setData(object);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_ONEPC_SUB_UPCONFIG + object.get("onepcHardwareNum"), messageBody, SendMode.ONCE);
    }

    /**
     * 发送传感器上线下线消息
     * context 发送内容
     */
    public void sendSensorNews(SensorStatus context) {

        MessageBody messageBody = new MessageBody();
        messageBody.setData(context);
        //仅发送一次
        commonSend.send(MqttConstants.LAB_SENSOR, messageBody, SendMode.ONCE);
    }
}
