package cn.minbb.iot.config;

import cn.minbb.iot.model.DeviceData;
import cn.minbb.iot.service.WebSocketService;
import cn.minbb.iot.util.Application;
import com.alibaba.fastjson.JSONObject;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;

/**
 * MQTT消息推送配置
 */
@Configuration
@IntegrationComponentScan
public class MqttSenderConfig {

    private Logger logger = LoggerFactory.getLogger(MqttSenderConfig.class);

    @Value("${spring.mqtt.username}")
    private String username;

    @Value("${spring.mqtt.password}")
    private String password;

    @Value("${spring.mqtt.url}")
    private String hostUrl;

    @Value("${spring.mqtt.client.id}")
    private String clientId;

    @Value("${spring.mqtt.default.topic}")
    private String defaultTopic;

    @Value("${spring.mqtt.completionTimeout}")
    private int completionTimeout;

    @Bean
    public MqttConnectOptions getMqttConnectOptions() {
        MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
        mqttConnectOptions.setUserName(username);
        mqttConnectOptions.setPassword(password.toCharArray());
        mqttConnectOptions.setServerURIs(new String[]{hostUrl});
        mqttConnectOptions.setKeepAliveInterval(2);
        return mqttConnectOptions;
    }

    @Bean
    public MqttPahoClientFactory mqttClientFactory() {
        DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
        factory.setConnectionOptions(getMqttConnectOptions());
        return factory;
    }

    @Bean
    @ServiceActivator(inputChannel = "mqttOutboundChannel")
    public MessageHandler mqttOutbound() {
        MqttPahoMessageHandler messageHandler = new MqttPahoMessageHandler(clientId, mqttClientFactory());
        messageHandler.setAsync(true);
        messageHandler.setDefaultTopic(defaultTopic);
        return messageHandler;
    }

    @Bean
    public MessageChannel mqttOutboundChannel() {
        return new DirectChannel();
    }

    /**
     * 接收通道
     */
    @Bean
    public MessageChannel mqttInputChannel() {
        return new DirectChannel();
    }

    // 配置 client，监听 topic
    @Bean
    public MessageProducer inbound() {
        MqttPahoMessageDrivenChannelAdapter adapter = new MqttPahoMessageDrivenChannelAdapter(
                clientId + "_inbound", mqttClientFactory(), defaultTopic,
                Const.MQTT_TOPIC_ALL, Const.MQTT_TOPIC_CAR, Const.MQTT_TOPIC_CAR_DATA);
        adapter.setCompletionTimeout(completionTimeout);
        adapter.setConverter(new DefaultPahoMessageConverter());
        adapter.setQos(1);
        adapter.setOutputChannel(mqttInputChannel());
        return adapter;
    }

    // 通过通道获取数据
    @Bean
    @ServiceActivator(inputChannel = "mqttInputChannel")
    public MessageHandler handler() {
        return message -> {
            Object object = message.getHeaders().get("mqtt_receivedTopic");
            String topic = null != object ? object.toString() : "";
            String msg = message.getPayload().toString();
            logger.info("收到消息 = 主题 = {}  信息 = {}", topic, msg);
            switch (topic) {
                case Const.MQTT_TOPIC_CAR_DATA:
                    try {
                        DeviceData data = JSONObject.parseObject(msg, DeviceData.class);
                        String longitudeString = data.getLongitude();
                        String latitudeString = data.getLatitude();
                        if (!longitudeString.isEmpty() && !latitudeString.isEmpty()) {
                            data.setLongitude(String.valueOf(Double.parseDouble(longitudeString.substring(0, 2)) + Double.parseDouble(longitudeString.substring(2, 10)) / 60));
                            data.setLatitude(String.valueOf(Double.parseDouble(latitudeString.substring(0, 3)) + Double.parseDouble(latitudeString.substring(3, 11)) / 60));
                        }
                        WebSocketService.sendInfo(
                                JSONObject.toJSONString(
                                        new DeviceData(data.getLongitude(), data.getLatitude(), Application.getCurrentStringTime())));
                    } catch (Exception e) {
                        logger.info("非JSON格式字符串 | {}", e.getMessage());
                    }
                    break;
                default:
            }
        };
    }
}
