package com.ruoyi.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.Topic;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisPubSubConfig {
    
    @Autowired
    private RedisConnectionFactory redisConnectionFactory;
    
    @Autowired
    private RedisMessageSubscriber redisMessageSubscriber;
    
    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);// 设置 Redis 连接
        
        // 订阅游戏房间频道
        Topic gameRoomTopic = new ChannelTopic("game_room_channel"); // 订阅的频道
        // 指定消息处理器（即redisMessageSubscriber的onMessage方法）
        container.addMessageListener(new MessageListenerAdapter(redisMessageSubscriber, "onMessage"), gameRoomTopic);// addMessageListener绑定监听器和频道
        /**
         * 整工作流程
         * 启动应用：Spring 初始化 RedisMessageListenerContainer，并建立与 Redis 的连接。
         * 订阅频道：容器开始监听 game_room_channel 频道。
         * 发布消息：其他服务或代码通过 Redis 的 PUBLISH 命令向 game_room_channel 发送消息，例如：
         * bash
         * PUBLISH game_room_channel "Hello, Game Room!"
         * 消息处理：
         * Redis 将消息推送给所有订阅者。
         * RedisMessageListenerContainer 接收到消息后，调用 RedisMessageSubscriber.onMessage() 方法。
         * 消息内容作为参数传递给 onMessage 方法，由开发者自定义处理逻辑（如更新游戏状态、广播通知等）。
          */
        /**
         * MessageListenerAdapter
         * 作用：将 Redis 消息转发到指定的处理器方法（这里是 redisMessageSubscriber.onMessage）。
         * 关键点：
         * 第二个参数 "onMessage" 指定处理器方法名（需在 RedisMessageSubscriber 中实现）。
         * 默认情况下，消息会以 byte[] 形式传递给处理器，Spring 会自动反序列化。
         */

        /***
         * 发布消息的步骤
         * 选择消息中间件：根据需求（如吞吐量、持久性、延迟）选择合适的工具。
         * 创建主题（Topic）或队列（Queue）：
         * 主题（Topic）：一对多广播（所有订阅者都能收到消息）。
         * 队列（Queue）：点对点（消息被一个订阅者消费）。
         * 发布消息：
         * 指定主题/队列名称。
         * 发送消息内容（通常是JSON、Protobuf等格式）。
         */
        return container;
    }
}