package com.red.circle.game.fruit.infrastructure.websocket;

import com.red.circle.game.fruit.infrastructure.websocket.config.PrincipalHandshakeHandler;
import com.red.circle.game.fruit.infrastructure.websocket.config.SocketHandshakeInterceptor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * 配置信息.
 *
 * @author pengliang on 2021/7/19
 */
@Configuration
@RequiredArgsConstructor
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

  // private final WebSocketDecoratorFactory webSocketDecoratorFactory;
  private final SocketHandshakeInterceptor socketHandshakeInterceptor;

  /**
   * 配置 WebSocket 进入点，及开启使用 SockJS，这些配置主要用配置连接端点，用于 WebSocket 连接.
   *
   * @param registry STOMP 端点
   */
  @Override
  public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/endpoint")
        .setAllowedOriginPatterns("*")
        .addInterceptors(socketHandshakeInterceptor)
        .setHandshakeHandler(new PrincipalHandshakeHandler())
        .withSockJS();
  }

  /**
   * 配置消息代理选项.
   *
   * @param registry 消息代理注册配置
   */
  @Override
  public void configureMessageBroker(MessageBrokerRegistry registry) {
    int serverHeartbeatSecond = 5 * 1000;
    int clientHeartbeatSecond = 5 * 1000;
    // 设置一个或者多个代理前缀.发送的消息，会首先转发到代理从而发送到对应广播或者队列中。
    registry.enableSimpleBroker("/topic", "/queue")
        .setHeartbeatValue(heartbeatValue(serverHeartbeatSecond, clientHeartbeatSecond))
        .setTaskScheduler(getThreadPoolTaskScheduler());
    // 配置客户端发送请求消息的一个或多个前缀
    registry.setApplicationDestinationPrefixes("/app");
    // 服务端通知特定用户客户端的前缀，可以不设置，默认为user
    registry.setUserDestinationPrefix("/user");
  }

  private ThreadPoolTaskScheduler getThreadPoolTaskScheduler() {
    ThreadPoolTaskScheduler te = new ThreadPoolTaskScheduler();
    te.setPoolSize(1);
    te.setThreadNamePrefix("websocket-heartbeat-thread-");
    te.initialize();
    return te;
  }

  private long[] heartbeatValue(long server, long client) {
    return new long[]{server, client};
  }

  /**
   * 配置通道拦截器，用于获取 Header 的 Token 进行鉴权.
   *
   * @param registration 注册通道配置类
   @Override public void configureClientInboundChannel(ChannelRegistration registration) {
   registration.interceptors(new CustomizeChannelInterceptor());
   } */

  /**
   * 添加 WebSocket 用户上、下线监听器.
   */
//  @Override
//  public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
//    registry.addDecoratorFactory(webSocketDecoratorFactory)
//        .setTimeToFirstMessage(60 * 3 * 1000);
//  }
  @Bean
  public CorsFilter corsFilter() {
    final CorsConfiguration corsConfiguration = new CorsConfiguration();
    corsConfiguration.setAllowCredentials(true);
    corsConfiguration.addAllowedOriginPattern(CorsConfiguration.ALL);
    // corsConfiguration.addAllowedOrigin(CorsConfiguration.ALL);
    corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
    corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);

    final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
    urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsFilter(urlBasedCorsConfigurationSource);
  }

}
