package com.sjyt.icom.asst.service.impl;

import cn.hutool.core.util.ObjectUtil;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通道组池，管理所有websocket连接
 *
 * @author renyanru
 * @version V1.0.0
 * {@code @date} 2022/5/27 11:28
 */
@Slf4j
@Component
public class ChannelPoolService {
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    public static Map<String, Channel> channelIdMap = new ConcurrentHashMap<>(16);

    public ChannelPoolService() {
    }

    /**
     * 新增一个客户端通道
     */
    public void addChannel(Channel channel) {
        channelGroup.add(channel);
    }

    /**
     * 移除一个客户端连接通道
     */
    public void removeChannel(Channel channel) {
        channelGroup.remove(channel);
    }

    /**
     * 新增一个客户端通道
     *
     * @param userId  用户id
     * @param channel 通道
     */
    public void addUserChannel(String userId, Channel channel) {
        channelIdMap.put(userId, channel);
    }

    /**
     * 移除一个客户端连接通道
     *
     * @param userId 用户id
     */
    public void delUserChannel(String userId) {
        channelIdMap.remove(userId);
    }

    /**
     * 移除一个客户端连接通道
     *
     * @param channel 用户通道
     */
    public void delUserChannel(Channel channel) {
        Optional<String> userId = getChannelForMap(channel);
        userId.ifPresent(this::delUserChannel);
    }

    /**
     * 返回Channel
     *
     * @param channelId channelId
     * @return Channel
     */
    public Optional<Channel> getChannel(ChannelId channelId) {
        return Optional.ofNullable(channelGroup.find(channelId));
    }

    public Optional<Channel> getChannel(String userId) {
        Optional<Channel> optionalChannel = Optional.ofNullable(channelIdMap.get(userId));
        if (optionalChannel.isPresent()) {
            return optionalChannel;
        } else {
            log.error("用户已下线");
            return Optional.empty();
        }
    }

    private Optional<String> getChannelForMap(Channel channel) {
        return channelIdMap.entrySet().stream()
                .filter(it -> ObjectUtil.equals(it.getValue().id(), channel.id()))
                .map(Map.Entry::getKey)
                .findFirst();
    }
}
