package com.fzm.mall.customer.service.websocket;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import com.fzm.mall.customer.service.customer.mapper.GroupUserMapper;
import com.fzm.mall.customer.service.customer.mapper.MessageMapper;
import com.fzm.mall.customer.service.customer.model.GroupUser;
import com.fzm.mall.customer.service.customer.model.Message;
import com.fzm.mall.customer.service.util.UUIDUtil;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * id：用户id
 * toId: 聊天室id
 */
@ServerEndpoint("/websocket/{id}/{toId}")
@Component
public class WebSocketServer {

    private static Integer ONLINE = 0;

    public static ConcurrentHashMap<String, WebSocketServer> WEBSOCKET_MAP = new ConcurrentHashMap<>();

    private Session session;

    private String userId;

    /**
     * 聊天组id
     */
    private String toId;

    private static GroupUserMapper groupUserMapper;

    private static MessageMapper messageMapper;

    public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {
        WebSocketServer.groupUserMapper = applicationContext.getBean(GroupUserMapper.class);
        WebSocketServer.messageMapper = applicationContext.getBean(MessageMapper.class);
    }

    @OnMessage
    public void onMessage(String messageStr) {
        Message message = JSON.parseObject(messageStr, Message.class);
        //心跳检测不入库
        if(!message.getMsgType().equals(Message.MESSAGE_TYPE_HEARTBEAT)){
            message.setSendTime(SystemClock.now());
            message.setMessageId(UUIDUtil.getUUID());
            messageMapper.insert(message);
        }
        WebSocketServer.sendToGroup(this.getUserByGroupId(message.getToId()), message.getToId(), message);
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id, @PathParam("toId") String toId) {
        this.userId = id;
        this.session = session;
        this.toId = toId;
        String key = id + toId;
        WebSocketServer webSocketServer = WEBSOCKET_MAP.get(key);
        if (webSocketServer == null) {
            WEBSOCKET_MAP.put(key, this);
        }
    }

    @OnClose
    public void onClose(@PathParam("id") String id, @PathParam("toId") String toId) {
        String key = id + toId;
        WEBSOCKET_MAP.remove(key);
    }

    public List<String> getUserByGroupId(String groupId) {
        return this.groupUserMapper.selectList(new LambdaQueryWrapper<GroupUser>().eq(GroupUser::getGroupId, groupId)).stream().map(GroupUser::getUserId).collect(Collectors.toList());
    }

    public static void sendToGroup(List<String> userIds, String toId, Message message) {
        for (String userId : userIds) {
            WebSocketServer.sendToOne(userId, toId, message);
        }
    }

    public static Future<Void> sendToOne(String userId, String toId, Message Message) {
        WebSocketServer webSocketServer = WEBSOCKET_MAP.get(userId + toId);
        if (webSocketServer == null) {
            //TODO 存放离线信息
        } else {
            return webSocketServer.session.getAsyncRemote().sendText(JSON.toJSONString(Message));
        }
        return null;
    }
}
