package com.m2pool.chat.config;

import com.m2pool.chat.constant.Destination;
import com.m2pool.chat.coverter.CommonMessageConvert;
import com.m2pool.chat.interceptor.WebsocketChannelInterceptor;
import com.m2pool.chat.interceptor.WebsocketHandshakeInterceptor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.concurrent.DefaultManagedTaskScheduler;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.messaging.StompSubProtocolHandler;
import org.springframework.web.socket.messaging.SubProtocolWebSocketHandler;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Description TODO
 * @Date 2025/2/25 14:43
 * @Author 杜懿
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketBrokerConfig implements WebSocketMessageBrokerConfigurer {



    @Resource
    private CustomWebSocketConfig customWebSocketConfig;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 注册 Stomp的端点 可以注册多个端点
     * addEndpoint：添加STOMP协议的端点。客户端访问地址
     * withSockJS：指定端点使用SockJS协议
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {

        //sockjs 形式端点
        registry.addEndpoint("/sockjs")
                .addInterceptors(new WebsocketHandshakeInterceptor())
                .setAllowedOrigins("*")
                .withSockJS();

        // websocket 形式端点
        registry.addEndpoint("/ws")
                .addInterceptors(new WebsocketHandshakeInterceptor())
                .setAllowedOrigins("*");
    }


    /**
     * 配置消息代理
     * 客户端订阅消息的请求前缀，topic用于广播推送，queue用于点对点推送
     * 启动简单Broker，消息的发送的地址符合配置的前缀来的消息才发送到这个broker
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {

        config.enableSimpleBroker(Destination.TOPIC, Destination.QUEUE_USER,Destination.QUEUE_CUSTOMER,Destination.QUEUE_CLOSE_ROOM)
                .setHeartbeatValue(new long[] {30000, 30000})
                .setTaskScheduler(new DefaultManagedTaskScheduler());

        //发送消息前缀
        config.setApplicationDestinationPrefixes(Destination.SEND_PREFIX);
        //客户端订阅前缀，可以不设置，默认为user
        config.setUserDestinationPrefix(Destination.USER_PREFIX);
    }


    /**
     * 最大消息字节数,发送超时时间,发送缓冲区大小,首次连接超时时间
     * @param registration
     */
    @Override
    public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
        registration
                .setMessageSizeLimit(customWebSocketConfig.getMessageSizeLimit())
                .setSendTimeLimit(customWebSocketConfig.getSendTimeLimit())
                .setSendBufferSizeLimit(customWebSocketConfig.getSendBufferSizeLimit());
                // 首次连接超时时间.正常情况下，前端订阅 和 心跳包的影响 不会超时断连
//                .setTimeToFirstMessage(customWebSocketConfig.getTimeToFirstMessage());
    }


//    @Bean
//    public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
//        ServletServerContainerFactoryBean factoryBean = new ServletServerContainerFactoryBean();
//        factoryBean.setMaxTextMessageBufferSize(customWebSocketConfig.getMessageSizeLimit());
//        factoryBean.setMaxBinaryMessageBufferSize(customWebSocketConfig.getMessageSizeLimit());
//        factoryBean.setMaxSessionIdleTimeout(2048L * 2048L);
//        factoryBean.setAsyncSendTimeout(2048L * 2048L);
//        return factoryBean;
//    }



    /**
     * 配置客户端出站通道拦截器（默认线程1）
     * 配置核心线程池 10 最大线程20 允许线程空闲时间 60
     * @param registration
     */
    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.taskExecutor().corePoolSize(10)
                .maxPoolSize(20)
                .keepAliveSeconds(60);
        // 拦截器配置
        registration.interceptors(new WebsocketChannelInterceptor(customWebSocketConfig,applicationEventPublisher));
    }

    /**
     * 配置消息转换器
     * @param messageConverters 转换器集合
     * @return 是否使用
     */
    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        messageConverters.add(new CommonMessageConvert());
        return true;
    }


}
