package com.business.socket;


import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.business.socket.bean.DataContent;
import com.business.socket.bean.PushModel;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import java.util.HashSet;
import java.util.Set;

//@ServerEndpoint("/business/app/websocket/{userId}")
//@Component
public class WebSocketServer {

    private Log log = LogFactory.get(WebSocketServer.class);
    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int onlineCount = 0;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String user) {


    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {

        WebSocketServerPool.removeUser(session);

        if (WebSocketServerPool.getUserByKey(session) == null) {
            subOnlineCount();
            //向所有用户通知当前用户下线消息
            PushModel model = new PushModel();
            model.add(new PushModel.Entity(PushModel.LOGOUT, "用户【"+WebSocketServerPool.getUserByKey(session)+"】退出"));
            WebSocketServerPool.sendMessage(model);
        }

    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
//        log.info("用户消息:" + WebSocketServerPool.getUserByKey(session) + ",报文:" + message);

        DataContent data = null;

        try {

            data = JSONObject.toJavaObject(JSON.parseObject(message), DataContent.class);

            // 获取客户端发来的消息
            Integer action = data.getAction();
            if (action == PushModel.CONNECT) {
                String user = data.getSender();

                //如果当前用户在连接池中没有socket信息，说明是新用户，在线人数加1
                if (WebSocketServerPool.getWebSocketByUser(user) == null) {
                    addOnlineCount();
                }

                // 当websocket 第一次open的时候，初始化session，把用的session和user关联起来
                //将当前用户加入到连接池中
                WebSocketServerPool.addUser(session, user);

                log.info("用户连接:" + user + ",当前在线人数为:" + getOnlineCount());

            } else if (action == PushModel.MESSAGE) {
                // 正常信息
                log.info("收到来自[" + data.getSender() + "]的心消息..." + data.getMessage());

            }else if (action == PushModel.KEEPALIVE) {
                // 心跳类型的消息
                log.info("收到来自[" + data.getSender() + "]的心跳包...");
            }

        } catch (Exception e) {
            if (data != null) {
                PushModel model = new PushModel();
                model.add(new PushModel.Entity(PushModel.MESSAGE, e.getMessage()));
                Set<String> users = new HashSet<String>();
                users.add(data.getSender());
                WebSocketServerPool.sendMessageToUser(users, model);
            }
        }

    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:" + WebSocketServerPool.getUserByKey(session) + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

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

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

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

}
