package com.wecloud.im.ws.service.impl;

import com.wecloud.im.ws.cache.UserCacheService;
import com.wecloud.im.ws.model.ClientInfo;
import com.wecloud.im.ws.model.redis.ClientChannelInfo;
import com.wecloud.im.ws.service.MangerChannelService;
import com.wecloud.rtc.service.RtcService;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Description 维护netty用户channel对象
 * @Author hewei hwei1233@163.com
 * @Date 2019-12-03
 */
@Component
@Slf4j
public class MangerChannelServiceImpl implements MangerChannelService {

    @Autowired
    private RtcService rtcService;

    @Autowired
    private UserCacheService userCacheService;

//    @Override
//    public NioSocketChannel get(String appKey, String clientId) {
//
//        return this.CHANNEL_MAP.get(appKey + clientId);
//    }

    @Override
    public void online(String appKey, String clientId, NioSocketChannel channel) {

        // 断掉旧链接
//        NioSocketChannel nioSocketChannel = get(appKey, clientId);
//        if (null != nioSocketChannel) {
//            log.info("put新连接关掉旧链接:" + appKey + "," + clientId + ",\nchannelId:" + nioSocketChannel.id().asLongText());
//            nioSocketChannel.close();
//        }

//        this.CHANNEL_MAP.put(appKey + clientId, channel);

        String longChannelId = channel.id().asLongText();
        this.putClientsMap(appKey, clientId, longChannelId);
        this.putSessionInfoMap(longChannelId, channel);

        userCacheService.online(appKey, clientId, longChannelId);
    }

    void putSessionInfoMap(String longChannelId, NioSocketChannel channel) {
        ClientInfo clientInfo = new ClientInfo();
        clientInfo.setDeviceId("");
        clientInfo.setNioSocketChannel(channel);
        clientInfo.setToken("");
        this.SESSION_INFO_MAP.put(longChannelId, clientInfo);
    }

    void putClientsMap(String appKey, String clientId, String longChannelId) {
        Set<String> set = this.CLIENTS_MAP.get(appKey + ":" + clientId);
        if (set == null || set.isEmpty()) {
            HashSet<String> hashSet = new HashSet<>();
            hashSet.add(longChannelId);
            this.CLIENTS_MAP.put(appKey + ":" + clientId, hashSet);
        } else {
            set.add(longChannelId);
        }
    }

    void delSessionInfoMap(String longChannelId) {
        this.SESSION_INFO_MAP.remove(longChannelId);
    }

    void delClientsMap(String appKey, String clientId, String longChannelId) {
        Set<String> set = this.CLIENTS_MAP.get(appKey + ":" + clientId);
        if (set != null) {
            set.remove(longChannelId);
        }
    }

    @Override
    public void offline(ChannelHandlerContext channelHandlerContext) {

        String appKey = channelHandlerContext.channel().attr(MangerChannelService.APP_KEY).get();
        String clientId = channelHandlerContext.channel().attr(MangerChannelService.CLIENT_ID).get();

        String userIdByChannelString = this.getStringInfoByChannel(channelHandlerContext);

        String longChannelId = channelHandlerContext.channel().id().asLongText();
        log.info("uid:" + userIdByChannelString + "," + "handlerRemoved" + ",channelId:" + longChannelId);

        // 关掉连接
        channelHandlerContext.close();


        // 移除本地维护的channel
        delSessionInfoMap(longChannelId);
        delClientsMap(appKey, clientId, longChannelId);

        // 移除redis缓存
        userCacheService.offline(appKey, clientId, longChannelId);

        // rtc清空缓存
        rtcService.clientOffline(appKey, clientId);

    }

    @Override
    public String getStringInfoByChannel(ChannelHandlerContext channelHandlerContext) {
        return "APP_KEY:" + channelHandlerContext.channel().attr(MangerChannelService.APP_KEY).get()
                + ",CLIENT_ID:" + channelHandlerContext.channel().attr(MangerChannelService.CLIENT_ID).get();
    }

//    @Override
//    public Boolean isOnLocal(Long userId) {
//        NioSocketChannel nioSocketChannel = this.get(String.valueOf(userId));
//        return null != nioSocketChannel;
//    }

    /**
     * 获取用户在线状态
     *
     * @param toAppKey
     * @param toClientId
     * @return true:在线, false 不在线
     */
    @Override
    public boolean getOnlineStatus(String toAppKey, String toClientId) {

        List<ClientChannelInfo> channelInfos = userCacheService.getIpByClientIdAndOnline(toAppKey, toClientId);

        boolean flag = false;
        for (ClientChannelInfo channelInfo : channelInfos) {

            if (channelInfo.getOnlineStatus().equals(1)) {
                return true;
            }
        }

//        NioSocketChannel nioSocketChannel = get(toAppKey, toClientId);
//        if (null == nioSocketChannel) {
//            if (log.isDebugEnabled()) {
//                log.info("writeData 不存在 连接为空:" + toAppKey + toClientId);
//            }
//            return false;
//        }
//        // 判断连接是否断开
//        if (nioSocketChannel.isShutdown()) {
//            if (log.isDebugEnabled()) {
//                log.info("writeData连接断开:" + toAppKey + toClientId + "channelId:" + nioSocketChannel.id().asLongText());
//            }
//            return false;
//        }
        return flag;
    }


//    @Override
//    public boolean writeData(String msg, String toAppKey, String toClientId) {
//
//        NioSocketChannel nioSocketChannel = get(toAppKey, toClientId);
//        if (null == nioSocketChannel) {
//                log.info("writeData连接为空:" + toAppKey + toClientId + "," + msg);
//            return false;
//        }
//        // 判断连接是否断开
//        if (nioSocketChannel.isShutdown()) {
//                log.info("writeData连接断开:" + toAppKey + toClientId + "," + msg + ",\nchannelId:" + nioSocketChannel.id().asLongText());
//            return false;
//        }
//
//        log.info("writeData:" + toAppKey + "," + toClientId + "," + msg + ",\nchannelId:" + nioSocketChannel.id().asLongText());
//
//        ChannelFuture channelFuture = nioSocketChannel.writeAndFlush(new TextWebSocketFrame(msg));
//        channelFuture.addListener(
//                //执行后回调的方法
//                (ChannelFutureListener) channelFuture1 -> {
//                    if (log.isDebugEnabled()) {
//                        log.info("netty线程异步执行结果:" + channelFuture1.isDone() + ",业务执行结果:" + channelFuture1.isSuccess()
//                                + "；\nwriteData:" + toAppKey + toClientId + "," + msg + ",channelId:" + nioSocketChannel.id().asLongText());
//                    }
//                });
//        return true;
//    }

    @Override
    public boolean writeDataToChannel(String msg, String toChannelId) {

        ClientInfo clientInfo = SESSION_INFO_MAP.get(toChannelId);
        if (clientInfo == null) {
            return false;
        }

        NioSocketChannel nioSocketChannel = clientInfo.getNioSocketChannel();
        if (null == nioSocketChannel) {
            log.info("writeData连接为空:" + msg);
            return false;
        }
        // 判断连接是否断开
        if (nioSocketChannel.isShutdown()) {
            log.info("writeData连接断开:" + msg + ",\nchannelId:" + nioSocketChannel.id().asLongText());
            return false;
        }

        log.info("writeData:" + ",\nchannelId:" + nioSocketChannel.id().asLongText());

        nioSocketChannel.writeAndFlush(new TextWebSocketFrame(msg));

        return true;
    }

}
