package tech.glinfo.enbao.modules.mqtt.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import tech.glinfo.enbao.common.contants.Constants;
import tech.glinfo.enbao.common.utils.ByteUtils;
import tech.glinfo.enbao.common.utils.EncryptUtil;
import tech.glinfo.enbao.common.utils.MapUtils;
import tech.glinfo.enbao.common.utils.RedisUtils;
import tech.glinfo.enbao.modules.sh.entity.ShDeviceEntity;
import tech.glinfo.enbao.modules.sh.entity.ShInstructionParsingEntity;
import tech.glinfo.enbao.modules.sh.entity.ShProductEntity;
import tech.glinfo.enbao.modules.sh.service.OtherShDeviceService;
import tech.glinfo.enbao.modules.sh.service.ShProductService;

import javax.jms.Topic;
import java.util.*;

@Slf4j
@Service
public class MqttService {
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private OtherShDeviceService otherShDeviceService;
    @Autowired
    private ShProductService shProductService;
    @Autowired
    private JmsMessagingTemplate jmsTemplate;
    @Autowired
    private Topic socketioTopic;
    @Autowired
    private RedisTemplate redisTemplate;

    public void msgHandle(String topic, String msg) {
        String[] topics = topic.split("/");
        ShDeviceEntity device = otherShDeviceService.deviceInfo(new MapUtils().put("numbering", topics[1]));
        Map<String, Object> ws = new HashMap<>();//推送给socketio
        if(topic.endsWith("data/up")) { //数据上报
            String type = msg.substring(2,4);
            if("01".startsWith(type)) {//实时数据上报
                if(device != null) {
                    //查询解析指令集
                    List<ShInstructionParsingEntity> cmds = otherShDeviceService.getDeviceInstructionList(device.getProductId(), "01");
                    if (cmds != null && cmds.size() > 0) {
                        int length = 0;
                        //解析设备报文内容
                        Map<String, Object> map = new HashMap<>();
                        for (ShInstructionParsingEntity cmd : cmds) {
                            String hex = msg.substring(length, length + cmd.getLength());
                            String hex1;
                            if (cmd.getType() == 1) {//整数
                                hex1 = String.valueOf(Integer.valueOf(hex, 16));
                            } else if(cmd.getType() == 2) {//字符串
                                hex1 = hex;
                            } else {//有符号整数
                                hex1 = ByteUtils.signHex2IntString(hex);
                            }
                            map.put(cmd.getName(), hex1);
                            length += cmd.getLength();
                        }
                        ws.putAll(map);
                        otherShDeviceService.updateDeviceData(JSON.toJSONString(map), device.getId());
                    }
                }
            } else if("02".startsWith(type)) {//设备信息上报
                String mac = ByteUtils.hexToString(msg.substring(8, 32));
                log.info("mac:{}", mac);
                if (redisUtils.hasKey("device:save:GL" + mac)) {
                    log.debug("添加设备:{}", mac);
                    String[] userId = redisUtils.get("device:save:GL" + mac).split("-");
                    String deviceFlag = topics[1].substring(0,3);
//                    int dnleng = Integer.valueOf(msg.substring(32, 34), 16);
//                    String deviceNo = ByteUtils.hexToString(msg.substring(34, 34 + dnleng));
                    log.info("deviceNo:{}", topics[1]);
                    ShProductEntity product = shProductService.getOne(new QueryWrapper<ShProductEntity>().eq("device_flag", deviceFlag).last("LIMIT 1"));
                    ShDeviceEntity shDevice = new ShDeviceEntity();
                    shDevice.setUserId(Integer.valueOf(userId[0]));
                    shDevice.setOnlineStatus(2);//在线
                    shDevice.setMac("GL"+mac);
                    shDevice.setFamilyId(Integer.valueOf(userId[1]));
                    shDevice.setNumbering(topics[1]);
                    shDevice.setName(product.getName());
                    shDevice.setPic(product.getPic());
                    shDevice.setProductId(product.getId());
                    shDevice.setSpareOne(EncryptUtil.encrypt(topics[1]));//保存设备连接密码
                    otherShDeviceService.save(shDevice);
                    redisUtils.delete("device:save:GL" + mac);
//                    jmsTemplate.convertAndSend(socketioTopic, JSON.toJSONString(new MapUtils().put("deviceId", "GL"+mac)));
                    //采用redis的订阅发布
                    redisTemplate.convertAndSend(Constants.REIDS_TOPIC, JSON.toJSONString(new MapUtils().put("deviceId", "GL"+mac)));
                }
                return;
            }
        }

        if(device != null) {//设备存在
            ws.put("deviceId", String.valueOf(device.getId()));
            ws.put("_msg", msg);
            ws.put("_topic", topic);
            //推送到socketio
            redisTemplate.convertAndSend(Constants.REIDS_TOPIC, JSON.toJSONString(ws));
            if(device.getOnlineStatus() != 2) {//设备上线推送
                List<Map<String, String>> mapList = new ArrayList<>();
                Map<String, String> map1 = new HashMap<>();
                map1.put("deviceId", String.valueOf(device.getId()));
                map1.put("status", "2");
                mapList.add(map1);
                //采用redis的订阅发布
                redisTemplate.convertAndSend(Constants.REIDS_TOPIC, JSON.toJSONString(new MapUtils().put("deviceId", "onlineStatus").put("list", mapList)));
//                jmsTemplate.convertAndSend(socketioTopic, JSON.toJSONString(new MapUtils().put("deviceId", "onlineStatus").put("list", mapList)));
            }
            //更新设备状态为在线
            new Thread(() -> {
                ShDeviceEntity deviceEntity = new ShDeviceEntity();
                deviceEntity.setId(device.getId());
                deviceEntity.setOnlineStatus(topic.endsWith("/will/up")?3:2);//遗嘱消息就是下线，其他上线
                deviceEntity.setOnlineTime(new Date());
                otherShDeviceService.updateById(deviceEntity);
            }).start();
        }
    }

}
