package com.mosty.websocket.config;

import com.alibaba.fastjson.JSON;
import com.mosty.base.model.dto.websocket.WebSocketObject;
import com.mosty.websocket.remote.TbBaseAdaptRemoteService;
import lombok.SneakyThrows;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * sfz为身份证
 */
@ServerEndpoint("/socket/{sfz}/{uuid}")
@Component
public class WebSocketServer {

    // 记录当前在线连接数
    private static int onlineCount = 0;
    // 存放每个客户端对应WebSocket对象
    public static Map<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
    // 与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;
    // 身份证号
    private String sfz = "";
    // 多浏览器登录的区分UUID，保证session唯一
    private String uuid = "";
    @Resource
    private TbBaseAdaptRemoteService tbBaseAdaptRemoteService;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("sfz") String sfz, @PathParam("uuid") String uuid) {
        this.session = session;
        if (!webSocketMap.containsKey(sfz)) {
            addOnlineCount();
        }
        webSocketMap.put(sfz + ":" + uuid, this);
        System.out.println("有新窗口开始监听：身份证：" + sfz + ",uuid:" + uuid + ",当前人数为" + getOnlineCount());
        this.sfz = sfz;
        this.uuid = uuid;
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketMap.remove(sfz + ":" + uuid);
        subOnlineCount();
        System.out.println("连接关闭！,当前人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("收到来自窗口" + ":" + sfz + ":" + uuid + "的消息：" + message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 服务器推动消息
     */
    @SneakyThrows
    public void sendMessage(Map<String, Object> map) throws IOException {
        this.session.getBasicRemote().sendText(JSON.toJSONString(map));
    }


    /**
     * 根据身份证号关闭websocket
     */
    public static void closeConn(@PathParam("sfz") String sfz, @PathParam("uuid") String uuid) throws IOException {
        for (Map.Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
            String key = entry.getKey();
            WebSocketServer item = entry.getValue();
            if (key.equals(sfz + ":" + uuid)) {
                webSocketMap.remove(sfz + ":" + uuid);
                item.onClose();
                subOnlineCount();
            }
        }
    }

    public void sendBbMessage(WebSocketObject obj) throws IOException {
        Map<String, Object> map = new HashMap<>();
        map.put("type", obj.getType());
        map.put("data", obj.getObj());
        for (Map.Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
            WebSocketServer webSocketServer = entry.getValue();
            String sfz = webSocketServer.sfz;
            LinkedHashMap bb = (LinkedHashMap) obj.getObj();
            String ssbmdm = bb.get("ssbmdm").toString();
            // 查询是否拥有数据权限，拥有该数据权限才推送消息
            boolean flag = this.tbBaseAdaptRemoteService.getDataPermission(sfz, ssbmdm);
            if (flag) {
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                System.err.println("---------发送给用户：" + sfz + "-------");
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                System.err.println("--------------------------------------");
                webSocketServer.sendMessage(map);
            }
        }
    }

    // 发送消息
    public static void sendInfo(WebSocketObject obj) throws IOException {
        Map<String, Object> map = new HashMap<>();
        map.put("type", obj.getType());
        map.put("data", obj.getObj());
        // 如果是null,推送给所有人
        if (CollectionUtils.isEmpty(obj.getSfzList())) {
            for (Map.Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
                WebSocketServer webSocketServer = entry.getValue();
                webSocketServer.sendMessage(map);
            }
        } else if (!CollectionUtils.isEmpty(obj.getSfzList())) {
            // 身份证不为null，推送给个人
            for (Map.Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
                WebSocketServer webSocketServer = entry.getValue();
                String key = entry.getKey();
                key = key.split(":")[1];
                if (obj.getSfzList().contains(key)) {
                    webSocketServer.sendMessage(map);
                }
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}