//package com.sunyard.ssp.server;
//
//import cn.hutool.core.util.ObjectUtil;
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.JSONObject;
//import com.google.protobuf.Any;
//import com.google.protobuf.InvalidProtocolBufferException;
//import com.sunyard.ssp.common.exception.SspwebException;
//import com.sunyard.ssp.proto.control.Control;
//import lombok.AllArgsConstructor;
//import lombok.Getter;
//import lombok.SneakyThrows;
//import lombok.extern.slf4j.Slf4j;
//import lombok.val;
//import lombok.var;
//import redis.clients.jedis.BinaryJedisPubSub;
//import redis.clients.jedis.HostAndPort;
//import redis.clients.jedis.JedisCluster;
//import redis.clients.jedis.JedisPool;
//import redis.clients.jedis.JedisPoolConfig;
//
//import java.util.HashSet;
//import java.util.Iterator;
//import java.util.Set;
//import java.util.UUID;
//import java.util.concurrent.Callable;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.concurrent.ConcurrentLinkedQueue;
//import java.util.concurrent.ExecutionException;
//import java.util.concurrent.ExecutorService;
//import java.util.concurrent.Executors;
//import java.util.concurrent.Future;
//import java.util.concurrent.TimeUnit;
//import java.util.concurrent.locks.Condition;
//import java.util.concurrent.locks.ReentrantLock;
//
//
///**
// * 封装到 Server 的通信
// * 异步转同步
// */
//
//@Slf4j
//public class Messenger {
//
//    private static String channel = "MANAGER_CLUSTER";
//    private static JedisCluster jedisCluster;
//    private static Redis redisSubscribe;
//    private static Redis redisSubscribe2;
//    private static Redis redis;//Publish
//    private static Thread thread;
//    private static ExecutorService executorService = Executors.newFixedThreadPool(3 );
//    private static ConcurrentHashMap<String, Record> pendingMessageRecord = new ConcurrentHashMap<>();
//
//    private static JedisPool jedisPool = null;
//    private static JedisPool jedisPool2 = null;
//    private static JedisPool jedisPool3 = null;
//
//    private static String host ;
//    private static Integer port ;
//    private static  String password;
//    private static  String mode;
//    static {
//
//        // 只有 CLI 需要重置 channel
//        //channel = Control.Req.Origin.CLI + "_" + Config.global.system.name;
//
//        // 初始化
//        // 链接到 redis
//        Set<HostAndPort> nodes = new HashSet<>();
//        JSONArray ns = Config.global.messenger.redisCluster.getJSONArray("nodes");
//         password = Config.global.messenger.redisCluster.getString("password");
//         mode = Config.global.messenger.redisCluster.getString("mode");
//        JSONObject node = Config.global.messenger.redisCluster.getJSONObject("node");
//        host = node.getString("ip");
//        port = node.getInteger("port");
//        for (Object n : ns) {
//            JSONObject no = (JSONObject) n;
//            nodes.add(new HostAndPort(no.getString("ip"), no.getInteger("port")));
//        }
//
//        @AllArgsConstructor
//        class Msg extends BinaryJedisPubSub {
//
//            @Override
//            public void onMessage(byte[] channel, byte[] message) {
//
//
//                // 将 message 解析为 Res 对象
//                try {
//                    val res = Control.Res.parseFrom( message );
//                    val id = res.getId();
//
//                    val record = pendingMessageRecord.get(id);
//                    if ( null == record ){
//                        log.debug("没有找到消息 {} 的记录, 遗弃。", id);
//                    } else {
//
//                        record.lock.lock();
//                        try {
//                            if ( record instanceof SoloRecord ){
//                                log.debug("找到 Solo 消息 {} 的记录, 触发信号。", id);
//                                ((SoloRecord) record).res = res;
//                                ((SoloRecord) record).getCondition().signal();
//                            } else if ( record instanceof ClusterRecord ){
//                                log.debug("找到 Cluster 消息 {} 的记录, 触发阶段信号。", id);
//                                ((ClusterRecord) record).reslist.add( res );
//                                ((ClusterRecord) record).getStage().signal();
//                            }
//                        }finally {
//                            record.lock.unlock();
//                        }
//
//                    }
//
//                } catch (InvalidProtocolBufferException e) {
//                    e.printStackTrace();
//                }
//
//            }
//        }
//
//        JedisPoolConfig config = new JedisPoolConfig();
//       // config.setTestOnBorrow(false);
//        jedisCluster = new JedisCluster(nodes, 1000, 2000, 5, password, config);
//        if (jedisPool ==null){
//            //调试的时候的配置
//            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//            //连接池中的最大空闲连接
//            jedisPoolConfig.setMaxIdle(1000);
//            //连接池最大阻塞等待时间
//            //jedisPoolConfig.setMaxWaitMillis(10000);
//            //在获取连接的时候检查有效性
//            //jedisPoolConfig.setTestOnBorrow(true);
//            // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
//            jedisPoolConfig.setBlockWhenExhausted(false);
//            // 是否启用pool的jmx管理功能, 默认true
//            jedisPoolConfig.setJmxEnabled(true);
//            jedisPool = new JedisPool(jedisPoolConfig,host,port,10000,password);
//        }
//        if (jedisPool2 ==null){
//            //调试的时候的配置
//            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//            //连接池中的最大空闲连接
//            jedisPoolConfig.setMaxIdle(1000);
//            //连接池最大阻塞等待时间
//            //jedisPoolConfig.setMaxWaitMillis(10000);
//            //在获取连接的时候检查有效性
//            //jedisPoolConfig.setTestOnBorrow(true);
//            // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
//            jedisPoolConfig.setBlockWhenExhausted(false);
//            // 是否启用pool的jmx管理功能, 默认true
//            jedisPoolConfig.setJmxEnabled(true);
//            jedisPool2 = new JedisPool(jedisPoolConfig,host,port,10000,password);
//        }
//        if (jedisPool3 ==null){
//
//        }
//        redis = new Redis(jedisCluster, jedisPool2, password, mode);
//        redisSubscribe = new Redis(jedisCluster, jedisPool, password, mode);
//
//        thread = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                log.info("监听反馈消息 {}", channel);
//                redisSubscribe.subscribe(new Msg(), channel.getBytes() );
//
//            }
//        });
//        thread.setName("messenger");
//        thread.start();
//    }
//
//
//    public static Thread subscribe(final BinaryJedisPubSub jedisPubSub, String channel){
//        return new Thread(new Runnable() {
//            @Override
//            public void run() {
//                //调试的时候的配置
//                JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
//                //连接池中的最大空闲连接
//                jedisPoolConfig.setMaxIdle(1000);
//                //连接池最大阻塞等待时间
//                //jedisPoolConfig.setMaxWaitMillis(10000);
//                //在获取连接的时候检查有效性
//                //jedisPoolConfig.setTestOnBorrow(true);
//                // 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true
//                jedisPoolConfig.setBlockWhenExhausted(false);
//                // 是否启用pool的jmx管理功能, 默认true
//                jedisPoolConfig.setJmxEnabled(true);
//                jedisPool3 = new JedisPool(jedisPoolConfig,host,port,10000,password);
//
//                redisSubscribe2 = new Redis(jedisCluster, jedisPool3, password, mode);
//
//                log.info("监听Check消息 {}", channel);
//                redisSubscribe2.subscribe(jedisPubSub, channel.getBytes() );
//            }
//        });
//    }
//
//    public static String genId(){
//        return UUID.randomUUID().toString().replace("-", "");
//    }
//
//
//    public static Control.Res primarySyncCmd( String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException {
//        var c = System.currentTimeMillis();
//        var last = c - 120000L;
//        redis.zremrangeByScore("SERVER_CLUSTER", 0, last);
//        val servers = redis.zrevrange("SERVER_CLUSTER", 0, 9);
//        if (servers.size()<1){
//            throw new SspwebException("安全服务异常");
//        }
//
//
//        Iterator<String> it = servers.iterator();
//        String channel = servers.iterator().next();
//
//        // 方便调试的逻辑
//        // 如果配置了调试服务器，优先使用调试服务器
//        val debugServer = redis.get("DEBUG_SERVER");
//        if ( null != debugServer && servers.contains( debugServer ) ) {
//            channel = debugServer;
//        }
//
//        val req = Control.Req.newBuilder()
//                .setId(Messenger.genId())
//                .setOrigin(Control.Req.Origin.MANAGER)
//                .setFrom("CLUSTER")
//                .setCmd(cmd)
//                .setData(Any.pack(data))
//                .build();
//        return soloSyncCmd("SERVER_" + channel, req);
//    }
//
//
//    public static Control.Res soloSyncCmd(String channel, String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException {
//
//        val req = Control.Req.newBuilder()
//                .setId(Messenger.genId())
//                .setOrigin(Control.Req.Origin.MANAGER)
//                .setFrom("CLUSTER")
//                .setCmd(cmd)
//                .setData(Any.pack(data))
//                .build();
//        return soloSyncCmd(channel, req);
//    }
//    /**
//     * 同步通信
//     *
//     * @param req
//     * @return
//     */
//    public static Control.Res soloSyncCmd(String channel, Control.Req req) throws ExecutionException, InterruptedException {
//
//        var c = System.currentTimeMillis();
//        var last = c - 120000L;
//        redis.zremrangeByScore("SERVER_CLUSTER", 0, last);
//        val servers = redis.zrevrange("SERVER_CLUSTER", 0, 9);
//        if (servers.size()<1){
//            throw new SspwebException("安全服务异常");
//        }
//        log.info("SoloSyncCmd 发送消息到 sspserver id={} cmd={}", channel, req.getCmd());
//
//        // 发送请求
//        redis.publish(channel.getBytes(), req.toByteArray() );
//
//        // 单点通信创建一个信号量
//        final SoloRecord record = new SoloRecord();
//
//        // 记录请求
//        pendingMessageRecord.put( req.getId(), record );
//        Future future = executorService.submit(new Callable<Control.Res>() {
//
//            @Override
//            public Control.Res call() throws Exception {
//                //Thread.sleep(3000);
//                try {
//                    record.getLock().lock();
//                    // 等待信号量
//                    record.getCondition().await( Config.global.messenger.maxWaitTime , TimeUnit.SECONDS );
//
//                }catch ( InterruptedException e ){
//                    log.error("Solo 请求 {} {} 被打断，from={}, to={}", req.getId() , req.getCmd() , req.getFrom(), channel);
//                } finally {
//                    record.getLock().unlock();
//                }
//
//                // 返回结果
//                return record.res;
//            }
//        });
//        // 阻塞,等待子线程结束
//        return (Control.Res) future.get();
//
//    }
//
//
//    public static ConcurrentLinkedQueue<Control.Res> clusterSyncCmd( String cmd, com.google.protobuf.GeneratedMessageV3 data) throws ExecutionException, InterruptedException {
//        if (ObjectUtil.isNull(data) || StrUtil.isEmpty(data.toString())){
//            val req = Control.Req.newBuilder()
//                    .setId(Messenger.genId())
//                    .setOrigin(Control.Req.Origin.MANAGER)
//                    .setFrom("CLUSTER")
//                    .setCmd(cmd)
//                    .build();
//            return clusterSyncCmd("SERVER_CLUSTER", req, null);
//        } else {
//            val req = Control.Req.newBuilder()
//                    .setId(Messenger.genId())
//                    .setOrigin(Control.Req.Origin.MANAGER)
//                    .setFrom("CLUSTER")
//                    .setCmd(cmd)
//                    .setData(Any.pack(data))
//                    .build();
//            return clusterSyncCmd("SERVER_CLUSTER", req, null);
//        }
//
//    }
//    public static ConcurrentLinkedQueue<Control.Res> clusterSyncCmd(String channel, Control.Req req) throws ExecutionException, InterruptedException {
//        return clusterSyncCmd(channel, req, null);
//    }
//
//    /**
//     * 集群同步通信
//     * 一个发送多个返回，收到是个数组。
//     *
//     * @param req
//     * @return
//     */
//    public static ConcurrentLinkedQueue<Control.Res> clusterSyncCmd(String channel, Control.Req req, ClusterRecordMoniter moniter) throws ExecutionException, InterruptedException {
//
//        // 发送请求
//        redis.publish(channel.getBytes(), req.toByteArray() );
//
//        // 单点通信创建一个信号量
//        final ClusterRecord record = new ClusterRecord();
//
//        // 记录请求
//        pendingMessageRecord.put( req.getId(), record );
//
//        // 监听阶段数据
//        executorService.submit(new Runnable() {
//
//            @SneakyThrows
//            @Override
//            public void run() {
//
//                try {
//                    record.getLock().lock();
//
//                    log.debug("等待阶段信号");
//                    record.getStage().await(Config.global.messenger.maxWaitTime , TimeUnit.SECONDS);
//                    log.debug("收到阶段信号");
//
//                    // 查询应该响应的数量
//                    val servers = redis.zrange("SERVER_CLUSTER", 0, 9);
//                    log.debug("应该收到的消息数 {}， 目前收到的消息数 {}", servers.size(), record.getReslist().size() );
//
//                    // 全部收到
//                    if ( servers.size() == record.getReslist().size() ){
//                        record.getCondition().signal();
//                    }
//
//
//                    if ( null != moniter ){
//                        moniter.onStage( servers.size(), record.getReslist(), record.getCondition() );
//                    }
//
//                } finally {
//                    record.getLock().unlock();
//
//                }
//            }
//        });
//
//        // 监听整体
//        Future future = executorService.submit(new Callable<ConcurrentLinkedQueue<Control.Res>>() {
//            @Override
//            public ConcurrentLinkedQueue<Control.Res> call() throws Exception {
//
//                try {
//                    record.getLock().lock();
//                    record.getCondition().await(Config.global.messenger.maxWaitTime , TimeUnit.SECONDS);
//                    return record.getReslist();
//                } finally {
//                    record.getLock().unlock();
//                }
//            }
//        });
//
//        // 阻塞,等待子线程结束
//        return (ConcurrentLinkedQueue<Control.Res>) future.get();
//    }
//
//    @Getter
//    private abstract static class Record {
//        private final ReentrantLock lock = new ReentrantLock();
//    }
//
//    @Getter
//    private static class SoloRecord extends Record {
//        private Condition condition = getLock().newCondition();
//        // 返回一个结果
//        private Control.Res res;
//    }
//
//    @Getter
//    private static class ClusterRecord extends Record {
//        private Condition stage = getLock().newCondition();
//        private Condition condition = getLock().newCondition();
//
//        // 返回一组结果
//        private final ConcurrentLinkedQueue<Control.Res> reslist = new ConcurrentLinkedQueue<>();
//    }
//
//    /**
//     * 允许监听集群命令的中间阶段
//     */
//    public abstract static class ClusterRecordMoniter {
//
//        /**
//         *
//         * @param curAliveServerNum - 当前集群中存活的服务数量，及期望响应的数量
//         * @param reslist - 当前已经收集的返回结果
//         * @param condition - 终结信号量 condition.signal(); 可以提前终结等待。
//         */
//        public abstract void onStage( int curAliveServerNum,  ConcurrentLinkedQueue<Control.Res> reslist , Condition condition );
//
//    }
//
//}
