package com.yanzhu.module.iot.gateway.config;

import com.yanzhu.module.iot.core.biz.IotDeviceCommonApi;
import com.yanzhu.module.iot.core.messagebus.core.IotMessageBus;
import com.yanzhu.module.iot.gateway.protocol.emqx.IotEmqxAuthEventProtocol;
import com.yanzhu.module.iot.gateway.protocol.emqx.IotEmqxDownstreamSubscriber;
import com.yanzhu.module.iot.gateway.protocol.emqx.IotEmqxUpstreamProtocol;
import com.yanzhu.module.iot.gateway.protocol.http.IotHttpDownstreamSubscriber;
import com.yanzhu.module.iot.gateway.protocol.http.IotHttpUpstreamProtocol;
import com.yanzhu.module.iot.gateway.protocol.mqtt.IotMqttDownstreamSubscriber;
import com.yanzhu.module.iot.gateway.protocol.mqtt.IotMqttUpstreamProtocol;
import com.yanzhu.module.iot.gateway.protocol.mqtt.manager.IotMqttConnectionManager;
import com.yanzhu.module.iot.gateway.protocol.mqtt.router.IotMqttDownstreamHandler;
import com.yanzhu.module.iot.gateway.protocol.mqttws.IotMqttWsDownstreamSubscriber;
import com.yanzhu.module.iot.gateway.protocol.mqttws.IotMqttWsUpstreamProtocol;
import com.yanzhu.module.iot.gateway.protocol.mqttws.manager.IotMqttWsConnectionManager;
import com.yanzhu.module.iot.gateway.protocol.mqttws.router.IotMqttWsDownstreamHandler;
import com.yanzhu.module.iot.gateway.protocol.tcp.IotTcpDownstreamSubscriber;
import com.yanzhu.module.iot.gateway.protocol.tcp.IotTcpUpstreamProtocol;
import com.yanzhu.module.iot.gateway.protocol.tcp.manager.IotTcpConnectionManager;
import com.yanzhu.module.iot.gateway.service.device.IotDeviceService;
import com.yanzhu.module.iot.gateway.service.device.message.IotDeviceMessageService;
import io.vertx.core.Vertx;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

@Configuration
@EnableConfigurationProperties(IotGatewayProperties.class)
@ConditionalOnClass(IotDeviceCommonApi.class) // 仅在IoT Device API可用时加载
@Slf4j
public class IotGatewayConfiguration {

    /**
     * IoT 网关 HTTP 协议配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "yanzhu.iot.gateway.protocol.http", name = "enabled", havingValue = "true")
    @Slf4j
    public static class HttpProtocolConfiguration {

        @Bean
        public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties) {
            return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp());
        }

        @Bean
        public IotHttpDownstreamSubscriber iotHttpDownstreamSubscriber(IotHttpUpstreamProtocol httpUpstreamProtocol,
                IotMessageBus messageBus) {
            return new IotHttpDownstreamSubscriber(httpUpstreamProtocol, messageBus);
        }
    }

    /**
     * IoT 网关 EMQX 协议配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "yanzhu.iot.gateway.protocol.emqx", name = "enabled", havingValue = "true")
    @Slf4j
    public static class EmqxProtocolConfiguration {

        @Bean(name = "emqxVertx", destroyMethod = "close")
        public Vertx emqxVertx() {
            return Vertx.vertx();
        }

        @Bean
        public IotEmqxAuthEventProtocol iotEmqxAuthEventProtocol(IotGatewayProperties gatewayProperties,
                                                                 @Qualifier("emqxVertx") Vertx emqxVertx) {
            return new IotEmqxAuthEventProtocol(gatewayProperties.getProtocol().getEmqx(), emqxVertx);
        }

        @Bean
        public IotEmqxUpstreamProtocol iotEmqxUpstreamProtocol(IotGatewayProperties gatewayProperties,
                                                               @Qualifier("emqxVertx") Vertx emqxVertx) {
            return new IotEmqxUpstreamProtocol(gatewayProperties.getProtocol().getEmqx(), emqxVertx);
        }

        @Bean
        public IotEmqxDownstreamSubscriber iotEmqxDownstreamSubscriber(IotEmqxUpstreamProtocol mqttUpstreamProtocol,
                IotMessageBus messageBus) {
            return new IotEmqxDownstreamSubscriber(mqttUpstreamProtocol, messageBus);
        }
    }

    /**
     * IoT 网关 TCP 协议配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "yanzhu.iot.gateway.protocol.tcp", name = "enabled", havingValue = "true")
    @Slf4j
    public static class TcpProtocolConfiguration {

        @Bean(name = "tcpVertx", destroyMethod = "close")
        public Vertx tcpVertx() {
            return Vertx.vertx();
        }

        @Bean
        public IotTcpUpstreamProtocol iotTcpUpstreamProtocol(IotGatewayProperties gatewayProperties,
                                                             IotDeviceService deviceService,
                                                             IotDeviceMessageService messageService,
                                                             IotTcpConnectionManager connectionManager,
                                                             @Qualifier("tcpVertx") Vertx tcpVertx) {
            return new IotTcpUpstreamProtocol(gatewayProperties.getProtocol().getTcp(),
                    deviceService, messageService, connectionManager, tcpVertx);
        }

        @Bean
        public IotTcpDownstreamSubscriber iotTcpDownstreamSubscriber(IotTcpUpstreamProtocol protocolHandler,
                                                                     IotDeviceMessageService messageService,
                                                                     IotDeviceService deviceService,
                                                                     IotTcpConnectionManager connectionManager,
                                                                     IotMessageBus messageBus) {
            return new IotTcpDownstreamSubscriber(protocolHandler, messageService, deviceService, connectionManager,
                    messageBus);
        }

    }

    /**
     * IoT 网关 MQTT 协议配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "yanzhu.iot.gateway.protocol.mqtt", name = "enabled", havingValue = "true")
    @Slf4j
    public static class MqttProtocolConfiguration {

        @Bean(name = "mqttVertx", destroyMethod = "close")
        public Vertx mqttVertx() {
            return Vertx.vertx();
        }

        @Bean
        public IotMqttUpstreamProtocol iotMqttUpstreamProtocol(IotGatewayProperties gatewayProperties,
                                                               IotDeviceMessageService messageService,
                                                               IotMqttConnectionManager connectionManager,
                                                               @Qualifier("mqttVertx") Vertx mqttVertx) {
            return new IotMqttUpstreamProtocol(gatewayProperties.getProtocol().getMqtt(), messageService,
                    connectionManager, mqttVertx);
        }

        @Bean
        public IotMqttDownstreamHandler iotMqttDownstreamHandler(IotDeviceMessageService messageService,
                                                                 IotMqttConnectionManager connectionManager) {
            return new IotMqttDownstreamHandler(messageService, connectionManager);
        }

        @Bean
        public IotMqttDownstreamSubscriber iotMqttDownstreamSubscriber(IotMqttUpstreamProtocol mqttUpstreamProtocol,
                                                                       IotMqttDownstreamHandler downstreamHandler,
                                                                       IotMessageBus messageBus) {
            return new IotMqttDownstreamSubscriber(mqttUpstreamProtocol, downstreamHandler, messageBus);
        }

    }

    /**
     * IoT 网关 MQTT WebSocket 协议配置类
     */
    @Configuration
    @ConditionalOnProperty(prefix = "yanzhu.iot.gateway.protocol.mqtt-ws", name = "enabled", havingValue = "true")
    @Slf4j
    public static class MqttWsProtocolConfiguration {

        @Bean(name = "mqttWsVertx", destroyMethod = "close")
        public Vertx mqttWsVertx() {
            return Vertx.vertx();
        }

        @Bean
        public IotMqttWsUpstreamProtocol iotMqttWsUpstreamProtocol(IotGatewayProperties gatewayProperties,
                                                                   IotDeviceMessageService messageService,
                                                                   IotMqttWsConnectionManager connectionManager,
                                                                   @Qualifier("mqttWsVertx") Vertx mqttWsVertx) {
            return new IotMqttWsUpstreamProtocol(gatewayProperties.getProtocol().getMqttWs(),
                    messageService, connectionManager, mqttWsVertx);
        }

        @Bean
        public IotMqttWsDownstreamHandler iotMqttWsDownstreamHandler(IotDeviceMessageService messageService,
                                                                     IotDeviceService deviceService,
                                                                     IotMqttWsConnectionManager connectionManager) {
            return new IotMqttWsDownstreamHandler(messageService, deviceService, connectionManager);
        }

        @Bean
        public IotMqttWsDownstreamSubscriber iotMqttWsDownstreamSubscriber(IotMqttWsUpstreamProtocol mqttWsUpstreamProtocol,
                                                                           IotMqttWsDownstreamHandler downstreamHandler,
                                                                           IotMessageBus messageBus) {
            return new IotMqttWsDownstreamSubscriber(mqttWsUpstreamProtocol, downstreamHandler, messageBus);
        }

    }

}
