package cn.iocoder.yudao.module.system.config.mqtt.util;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.module.system.config.mqtt.MqttFactory;
import cn.iocoder.yudao.module.system.config.mqtt.MqttProperties;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
@Component
public class MqttUtils {

    @Autowired
    private MqttProperties config;

    private static final ExecutorService executorService = Executors.newFixedThreadPool(50);

    /**
     * 发布消息
     *
     * @param qos 0-至多1次、1-至少1次、2-一次
     * @param retained 是否保留：true-sub重新连接mqtt服务端时，总能拿到该主题的最新消息、false-sub重新连接mqtt服务端时，只能拿到连接后发布的消息
     * @param topic 话题
     * @param message 消息内容
     */
    public void pub(String topic, String message) {
        executorService.execute(() ->{
            send(topic, message);
        });
    }

    public void send(String topic, String message) {
        // 获取客户端实例
        MqttClient client = null;
        try {
            client = MqttFactory.getInstance();
        } catch (MqttException e) {
            log.info("获取客户端异常 :{}",e);
        }
        MqttMessage mqttMessage = new MqttMessage();
        mqttMessage.setQos(config.getQos());
        mqttMessage.setRetained(false);
        // 此处必须指明编码方式，否则会出现订阅端中文乱码的情况
        mqttMessage.setPayload(message.getBytes(StandardCharsets.UTF_8));
        // 主题的目的地，用于发布/订阅信息
        MqttTopic mqttTopic = client.getTopic(topic);
        // 提供一种机制来跟踪消息的传递进度
        // 用于在以非阻塞方式（在后台运行）执行发布是跟踪消息的传递进度
        MqttDeliveryToken token;
        try {
            // 将指定消息发布到主题，但不等待消息传递完成，返回的token可用于跟踪消息的传递状态
            // 一旦此方法干净地返回，消息就已被客户端接受发布，当连接可用，将在后台完成消息传递。
            token = mqttTopic.publish(mqttMessage);
            token.waitForCompletion();
        } catch (MqttException e) {
            log.info("MQTT");
        }

        if (PathPlanningTopicConstant.AGV_POSE.equals(topic)) {
            return;
        }

        if (message.length() > 1010) {
            log.info("111111发送的主题 :{}, 内容 :{}",topic, message.substring(0, 1000));
        }else {
            log.info("111111发送的主题 :{}, 内容 :{}",topic, message);
        }
    }

    /**
     * 断开连接
     */
    public static void disConnect() {
        try {
            // 获取客户端实例
            MqttClient client = MqttFactory.getInstance();
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}