package com.pwt.netty.util;

import com.alibaba.fastjson2.JSONObject;
import com.pwt.netty.conponents.WebSocketChannelRepository;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

/**
 * @author linyun
 * @version V1.0
 * @Title: WebSocketUtil
 * @Description: webSocket工具类
 * @date 2022/11/11
 **/
@Slf4j
public class WebSocketUtil {

    public static AttributeKey<String> userIdKey = AttributeKey.valueOf("userId");

    /**
     * @Description: 向指定客户端发送消息
     * @Author: linyun
     * @Date: 2022/11/13 13:01
     * @Param:[clientId 客户端ID, content 消息内容体,如果是对象自动转为json]
     * @Return:void
     **/
    public static <T> void pushMsgToOne(String clientId, T content)
    {
        SocketChannel channel = WebSocketChannelRepository.get(clientId);
        if (channel == null)
        {
            log.error("channel {} does not exist", clientId);
            return;
        }
        send(channel, content);
    }

    public static <T> void send(SocketChannel channel, T msg)
    {
        String content = JSONObject.toJSONString(msg);
        String userId = getChannelClientId(channel);
        if (channel.isActive())
        {
            channel.writeAndFlush(new TextWebSocketFrame(content)).addListener((ChannelFutureListener) channelFuture ->
            {
                if (channelFuture.isSuccess())
                {
//                    log.info("send msg to user:{} successful,content:{}", userId, JSONObject.toJSONString(content));
                } else
                {
                    log.info("send msg to user:{} failed,content:{}", userId, content);
                    closeChannel(channel);
                }
            });
        } else
        {
            closeChannel(channel);
        }
    }

    /**
     * @Description: 向指定通道发送消息
     * @Author: linyun
     * @Date: 2022/11/13 13:04
     * @Param:[channel 通道, content 消息内容体,如果是对象自动转为json]
     * @Return:void
     **/
    public static void send(SocketChannel channel, String content)
    {
        String userId = getChannelClientId(channel);
        if (channel.isActive())
        {
            channel.writeAndFlush(new TextWebSocketFrame(content)).addListener((ChannelFutureListener) channelFuture ->
            {
                if (channelFuture.isSuccess())
                {
//                    log.info("send msg to user:{} successful,content:{}", userId, JSONObject.toJSONString(content));
                } else
                {
                    log.info("send msg to user:{} failed,content:{}", userId, content);
                    closeChannel(channel);
                }
            });
        } else
        {
            closeChannel(channel);
        }
    }

    /**
     * @Description: 关闭通道
     * @Author: linyun
     * @Date: 2022/11/13 13:04
     * @Param:[channel 通道]
     * @Return:void
     **/
    public static void closeChannel(Channel channel)
    {
        channel.close();
        String userId = getChannelClientId(channel);
        if(userId != null) {
            WebSocketChannelRepository.remove(userId);
        }
    }

    /**
     * @Description: 获取通道ID
     * @Author: linyun
     * @Date: 2022/11/13 13:04
     * @Param:[channel 通道]
     * @Return:java.lang.String
     **/
    public static String getChannelClientId(Channel channel)
    {
        return channel.attr(userIdKey).get();
    }

    /**
     * @Description: 像所有webSocket客户端推送消息
     * @Author: linyun
     * @Date: 2022/11/13 13:05
     * @Param:[msg 消息对象]
     * @Return:void
     **/
    public static <T> void pushMsgToAll(T msg)
    {
        String content = JSONObject.toJSONString(msg);

        WebSocketChannelRepository.getChannels().values().forEach((channel) ->
        {
            send(channel, content);
        });

    }
}
