package tech.glinfo.enbao.modules.mq;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
import tech.glinfo.enbao.common.contants.AppContants;
import tech.glinfo.enbao.common.contants.Constants;
import tech.glinfo.enbao.common.utils.AppPush;
import tech.glinfo.enbao.common.utils.MapUtils;
import tech.glinfo.enbao.common.utils.RedisUtils;
import tech.glinfo.enbao.common.utils.SpringContextUtils;
import tech.glinfo.enbao.modules.sh.entity.ShDeviceEntity;
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 tech.glinfo.enbao.modules.socketio.SocketIOService;
import tech.glinfo.enbao.modules.sys.entity.ParseClassEntity;
import tech.glinfo.enbao.modules.sys.service.ParseClassService;
import tech.glinfo.enbao.modules.websocket.WebSocketServer;

import javax.jms.Topic;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

@Component
public class MqConsumer {

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

    @Autowired
    private JmsMessagingTemplate jmsTemplate;

    @Autowired
    private Topic websocketTopic;

    @Autowired
    private Topic socketioTopic;

    @Autowired
    private OtherShDeviceService otherShDeviceService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private AppPush appPush;

    @Autowired
    private ParseClassService parseClassService;

    @Autowired
    private ShProductService shProductService;

    @Autowired
    private SpeakerParse speakerParse;

    @Autowired
    private SocketIOService socketIOService;

    /**
     * 发送到websocket
     *
     * @param message
     */
    @JmsListener(destination = AppContants.WEBSOCKET_TOPIC, containerFactory = "jmsListenerContainerTopic")
    public void topic(String message) {
        logger.info("报文为：{}，主题:{}", message, AppContants.WEBSOCKET_TOPIC);
        try {
            Map<String, String> datas = (Map<String, String>) JSON.parse(message);
            WebSocketServer.sendByDeviceId(message, datas.get("deviceId"));
//            logger.info("send message to websocket success : {}", message);
        } catch (Exception e) {
            logger.error("parse message to websocket error : {}", e.getMessage());
        }
    }

    /**
     * 发送到websocket
     *
     * @param message
     */
    @JmsListener(destination = AppContants.SOCKETIO_TOPIC, containerFactory = "jmsListenerContainerTopic")
    public void socketioTopic(String message) {
        logger.info("报文为：{}，主题:{}", message, AppContants.SOCKETIO_TOPIC);
        try {
            Map<String, String> datas = (Map<String, String>) JSON.parse(message);
            socketIOService.pushMessageToDevice(datas.get("deviceId"), message);
//            logger.info("send message to websocket success : {}", message);
        } catch (Exception e) {
            logger.error("parse message to websocket error : {}", e.getMessage());
        }
    }

    /**
     * 接收iot云平台消息推送
     *
     * @param message
     */
    @JmsListener(destination = AppContants.RECEIVE_QUEUE, containerFactory = "jmsListenerContainerQueue")
    public void dequeue(String message) {
        logger.info("报文为：{}，主题:{}", message, AppContants.RECEIVE_QUEUE);

        try {
            Map<String, String> datas = (Map<String, String>) JSON.parse(message);
            if ("08".equals(datas.get("cmd"))) {
                //新增设备
                if (redisUtils.hasKey("device:save:" + datas.get("mac"))) {
                    String[] userId = redisUtils.get("device:save:" + datas.get("mac")).split("-");
                    ShProductEntity product = shProductService.getOne(new QueryWrapper<ShProductEntity>().eq("device_flag", datas.get("receiveId").substring(0, 3)).last("LIMIT 1"));
                    ShDeviceEntity shDevice = new ShDeviceEntity();
                    shDevice.setUserId(Integer.valueOf(userId[0]));
                    shDevice.setMac(datas.get("mac"));
                    shDevice.setFamilyId(Integer.valueOf(userId[1]));
                    shDevice.setNumbering(datas.get("receiveId"));
                    shDevice.setName(product.getName());
                    shDevice.setPic(product.getPic());
                    shDevice.setProductId(product.getId());
                    otherShDeviceService.save(shDevice);
                    redisUtils.delete("device:save:" + datas.get("mac"));
                    jmsTemplate.convertAndSend(socketioTopic, JSON.toJSONString(new MapUtils().put("deviceId", datas.get("mac"))));
                }
            }
            ShDeviceEntity device = otherShDeviceService.deviceInfo(new MapUtils().put("numbering", datas.get("receiveId")));
            if (device == null) {
                logger.error("设备不存在 : {}", datas.get("receiveId"));
                return;
            }
            //更新设备状态为在线
            new Thread(() -> {
                ShDeviceEntity deviceEntity = new ShDeviceEntity();
                deviceEntity.setId(device.getId());
                deviceEntity.setOnlineStatus(2);
                deviceEntity.setOnlineTime(new Date());
                otherShDeviceService.updateById(deviceEntity);
            }).start();


            String sendMessage = null;
            Map<String, String> ws = null;
//            redisUtils.get(Constants.PARSE_CLASS + datas.get("deviceType"));

            ParseClassEntity entity = redisUtils.get(Constants.PARSE_CLASS + datas.get("deviceType"), ParseClassEntity.class);
            if (entity == null) {
                entity = parseClassService.getOne(new QueryWrapper<ParseClassEntity>().eq("type", datas.get("deviceType")));
            }
            if (entity == null) {
                logger.info("找不到配置的解析类：deviceType={}", datas.get("deviceType"));
                return;
            } else {
                Object target = SpringContextUtils.getBean(entity.getClassName());
                Method method = target.getClass().getDeclaredMethod("run", Object.class, Map.class);
                ws = (Map<String, String>) method.invoke(target, device, datas);
            }
            if (ws == null || ws.isEmpty()) {
                return;
            }
            ws.put("deviceId", String.valueOf(device.getId()));
            sendMessage = JSON.toJSONString(ws);
            jmsTemplate.convertAndSend(socketioTopic, sendMessage);
//            logger.info("Message was sent to the websocket : {}", sendMessage);
        } catch (Exception e) {
            logger.error("MQ数据解析错误 : ", e);
        }
    }

    /**
     * 接收iot云平台消息推送
     * @param message
     */
    /*@JmsListener(destination = AppContants.EXPIRED_RECEIVE_QUEUE, containerFactory = "jmsListenerContainerQueue")
    public void expiredQueue(String message) {
//        logger.info("报文为：{}，主题:{}", message, AppContants.RECEIVE_QUEUE);
        logger.info("############接收超时，deviceNo:{}", message);
        new Thread(new Runnable() {
            @Override
            public void run() {
                speakerParse.combineDatas(message);
            }
        }).start();
    }*/

    /**
     * 接收iot云平台消息推送
     *
     * @param message
     */
    @JmsListener(destination = AppContants.PUSH_QUEUE, containerFactory = "jmsListenerContainerQueue")
    public void pushQueue(String message) {
        logger.info("报文为：{}，主题:{}", message, AppContants.PUSH_QUEUE);
        Map<String, String> datas = (Map<String, String>) JSON.parse(message);
        if (datas.get("title") != null && datas.get("content") != null && datas.get("clientId") != null) {
            appPush.push(datas.get("title"), datas.get("content"), datas.get("clientId"));
        }
    }
}
