package com.wecloud.im.ws.cache;

import com.wecloud.im.ws.model.redis.ClientChannelInfo;
import com.wecloud.im.ws.utils.InitIp;
import com.wecloud.im.ws.utils.RedisUtils;
import com.wecloud.im.ws.utils.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author hewei123@163.com
 * @Description 用户与redis绑定
 * @createTime 2020年04月14日 16:21:00
 */
@Service
@Slf4j
public class UserStateCacheManager extends UserStateListener {

    /**
     * 在线状态
     */
    public static final Integer ONLINE = 1;
    /**
     * 离线状态
     */
    public static final Integer OFFLINE = 0;
    /**
     * 维护client端的信息
     * ip及平台类型
     */
    private static final String CLIENT_INFO = "cli:";
    /**
     * 维护client的多端数据:
     * 值为set集合,netty的channel的id
     */
    private static final String CLIENTS = "cis:";
    /**
     * 用户在线状态fieldKey
     */
    private static final String ONLINE_STATUS = "ost";
    /**
     * 设备类型   web,ios,android,ios,other
     */
    private static final String DEVICE_TYPE = "ty";

    /**
     * 用户所连机器ip的fieldKey
     */
    private static final String LAN_IP = "lip";
    /**
     * 用户公网ip，在公网部署集群需要用到
     */
    private static final String PUBLIC_IP = "pip";
    /**
     * 推送token
     */
    private static final String DEVICE_TOKEN = "dt";
    /**
     * 设备ID
     */
    private static final String DEVICE_ID = "di";
    @Autowired
    private RedisUtils redisUtils;

    @Override
    public void onLineEvent(String appKey, String clientId, String longChannelId) {
        log.info("ws用户上线保存redis连接ip:" + InitIp.lAN_IP, ",uid:" + longChannelId);

        // 先进行历史数据清理
        Set<String> members = redisUtils.getForSetMembers(CLIENTS + appKey + clientId);
        if(members != null) {
            members.forEach(channelId-> redisUtils.delKey(CLIENT_INFO + channelId));
        }
        redisUtils.delKey(CLIENTS + appKey + clientId);

        redisUtils.addForSet(CLIENTS + appKey + clientId, longChannelId);
        redisUtils.hashset(CLIENT_INFO + longChannelId, LAN_IP, InitIp.lAN_IP);
        redisUtils.hashset(CLIENT_INFO + longChannelId, ONLINE_STATUS, ONLINE.toString());
    }

    @Override
    public void offlineEvent(String appKey, String clientId, String longChannelId) {
        log.info("ws用户离线删除redis key,uid:" + longChannelId);

        redisUtils.removeForSet(CLIENTS + appKey + clientId, longChannelId);

//        redisUtils.hashset(CLIENT_INFO + appKey + clientId, ONLINE_STATUS_KEY, OFFLINE.toString());
        redisUtils.delKey(CLIENT_INFO + longChannelId);
    }

    /**
     * 根据clientId获取redis 的channel信息
     * @param appKey
     * @param clientId
     * @return
     */
    public List<ClientChannelInfo> getIpByClientIdAndOnline(String appKey, String clientId) {

        // 获取所有 CLIENTS的 longChannelId
        Set<String> longChannelIds = redisUtils.getForSetMembers(CLIENTS + appKey + clientId);
        ArrayList<ClientChannelInfo> clientChannelInfos = new ArrayList<>();

        // 根据 longChannelId 查询信息
        for (String longChannelId : longChannelIds) {

            String onlineStatus = redisUtils.hashget(CLIENT_INFO + longChannelId, ONLINE_STATUS);
            String lanIp = redisUtils.hashget(CLIENT_INFO + longChannelId, LAN_IP);

            ClientChannelInfo clientChannelInfo = new ClientChannelInfo();
            clientChannelInfo.setChannelId(longChannelId);
            clientChannelInfo.setLanIp(lanIp);
            clientChannelInfo.setOnlineStatus(Integer.valueOf(onlineStatus));

            clientChannelInfos.add(clientChannelInfo);

//           //判断是否在线
//            if (StringUtils.isNotBlank(onlineStatus) && Integer.valueOf(onlineStatus).equals(ONLINE)) {
//            }
        }

        return clientChannelInfos;
    }

}
