package com.xjrsoft.common.mqtt;

import cn.hutool.core.util.IdUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.config.MqttConfig;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.mqttv5.client.IMqttMessageListener;
import org.eclipse.paho.mqttv5.client.MqttClient;
import org.eclipse.paho.mqttv5.client.MqttConnectionOptions;
import org.eclipse.paho.mqttv5.client.persist.MemoryPersistence;
import org.eclipse.paho.mqttv5.common.MqttException;
import org.eclipse.paho.mqttv5.common.MqttMessage;
import org.eclipse.paho.mqttv5.common.MqttSubscription;
import org.eclipse.paho.mqttv5.common.packet.MqttProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.Map;

/**
 * mqtt 链接
 */
@Component
@Slf4j
public class EmqClient {
    private MqttClient mqttClient;


    @Autowired
    private RedisUtil redisUtil;

    /**
     * 获取所有实现了IMqttMessageListener接口的类
     */
    @Autowired
    private MqttServiceLocator mqttServiceLocator;

    @PostConstruct
    private void init() {

        MqttConfig mqttConfig = SpringUtil.getBean(MqttConfig.class);

        if (mqttConfig.getServer() == null) {
            return;
        }

        MemoryPersistence persistence = new MemoryPersistence();
        try {
            mqttClient = new MqttClient(mqttConfig.getServer(), "tl" + IdUtil.simpleUUID(), persistence);
            //Paho Mqtt 连接参数
            MqttConnectionOptions connOpts = new MqttConnectionOptions();
            connOpts.setCleanStart(true);
            connOpts.setKeepAliveInterval(180);
            if (mqttConfig.getUsername() != null) {
                connOpts.setUserName(mqttConfig.getUsername());
                connOpts.setPassword(mqttConfig.getPassword().getBytes());
            }
            //Paho Mqtt5 设备上报QoS1&QoS2消息流控
            connOpts.setReceiveMaximum(5);
            //自动重连
            connOpts.setAutomaticReconnect(true);

            //Paho Mqtt5 设备接收的最大报文长度
//            connOpts.setMaximumPacketSize(1024L);

            mqttClient.connectWithResult(connOpts);

            // 订阅已实现的topic
            Map<String, IMqttMessageListener> allTopic = mqttServiceLocator.getMap();

            allTopic.forEach((k, v) -> {
                MqttSubscription[] subscriptions = new MqttSubscription[]{new MqttSubscription(k)};
                IMqttMessageListener[] subscriptionListeners = new IMqttMessageListener[]{v};
                try {
                    mqttClient.subscribe(subscriptions, subscriptionListeners);
                } catch (MqttException e) {
                    log.error(e.getMessage(), "mqtt 错误！");
                }
            });
        } catch (Exception e) {
            log.error(e.getMessage(), "mqtt 连接失败！");
        }
    }

    // 发送消息
    public void publish(String topic, Object msg) throws MqttException {
        if (mqttClient != null) {
            // 组装参数
            String msgStr = JSONUtil.toJsonStr(msg);
            MqttMessage message = new MqttMessage(msgStr.getBytes());
            message.setQos(1);

            String requestId = IdUtil.simpleUUID();

            MqttProperties properties = new MqttProperties();
            properties.setCorrelationData(requestId.getBytes());
            message.setProperties(properties);

            // 参数存入redis中
            redisUtil.set(GlobalConstant.MQTT_REQUEST_ID + requestId, msgStr, 86400);

            mqttClient.publish(topic, message);
        }
    }

    // 根据请求编号获取参数
    public String getRequestParams(String requestId) {
        return redisUtil.get(GlobalConstant.MQTT_REQUEST_ID + requestId);
    }
}
