package thyyxxk.webserver.websocket;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.utils.TokenUtil;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author dj
 */
@Slf4j
@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketServer {
    private static final AtomicInteger ONLINE_COUNT = new AtomicInteger();
    private static final ConcurrentHashMap<String, Session> SESSION_MAP = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("sid") String sid) {
        if ("update".equals(sid)) {
            return;
        }
        if (!sid.endsWith("Screen")) {
            SESSION_MAP.forEach((item, index) -> {
                if (sid.split("-")[0].equals(item.split("-")[0])) {
                    sendMessageByWebSocketSidSingle(item);
                }
            });
        }
        SESSION_MAP.put(sid, session);
        ONLINE_COUNT.incrementAndGet();
        log.info("有新连接加入：{}，当前在线人数为：{}", sid, ONLINE_COUNT.get());
    }

    @OnClose
    public void onClose(@PathParam("sid") String sid) {
        SESSION_MAP.remove(sid);
        ONLINE_COUNT.decrementAndGet();
        log.info("有一连接关闭：{}，当前在线人数为：{}", sid, ONLINE_COUNT.get());
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("收到信息：{}", message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("【session id: " + session.getId() + "】Socket连接发生错误", error);
    }

    public static String getSid() {
        String token = TokenUtil.getTokenUserId();
        for (Map.Entry<String, Session> entry : SESSION_MAP.entrySet()) {
            if (entry.getKey().startsWith(token)) {
                return entry.getKey();
            }
        }
        return "";
    }



    public static int sendMessage(String sid, String message) {
        Session session = SESSION_MAP.get(sid);
        if (null == session) {
            return ExceptionEnum.NULL_POINTER.getCode();
        }
        try {
            session.getBasicRemote().sendText(message);
            return 200;
        } catch (Exception e) {
            log.error("【sid: " + sid + "】Socket根据sid发送消息出错", e);
            return ExceptionEnum.INTERNAL_SERVER_ERROR.getCode();
        }
    }

    public static void sendFloorTriageMessage(String userCode, String message) {
        for (Map.Entry<String, Session> entry : SESSION_MAP.entrySet()) {
            if (entry.getKey().startsWith(userCode) && entry.getKey().endsWith("triageFloorScreen")) {
                try {
                    entry.getValue().getBasicRemote().sendText(message);
                    return;
                } catch (Exception e) {
                    log.error("【sid: " + userCode + "】Socket发送导诊台通知出错", e);
                    return;
                }
            }
        }
    }

    public static void sendRoomTriageMessage(String roomCode, String message) {
        Session session = SESSION_MAP.get(roomCode + "-triageRoomScreen");
        if (null == session) {
            return;
        }
        try {
            session.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("【sid: " + roomCode + "】Socket发送诊室屏显通知出错", e);
        }
    }

    public static void sendMessageByUserCode(String code, String message) {
        for (Map.Entry<String, Session> entry : SESSION_MAP.entrySet()) {
            if (entry.getKey().startsWith(code)) {
                try {
                    entry.getValue().getBasicRemote().sendText(message);
                } catch (IOException e) {
                    log.error("【sid: " + code + "】Socket根据人员code发送消息出错", e);
                }
                break;
            }
        }
    }

    /**
     * 单个登陆不能有多个账号同时登陆
     *
     * @param sid 被挤掉的连接
     */
    public static void sendMessageByWebSocketSidSingle(String sid) {
        JSONObject obj = new JSONObject();
        obj.put("name", "sidSingle");
        try {
            SESSION_MAP.get(sid).getBasicRemote().sendText(obj.toString());
        } catch (IOException e) {
            e.printStackTrace();
            log.error("【sid: " + sid + "】Socket根据单点登陆错误", e);
        }

    }

    public static void sendMessageToAll(String message) {
        for (Session session : SESSION_MAP.values()) {
            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                log.error("Socket发送全体消息出错", e);
            }
        }
    }

    public static int getOnlineCount() {
        return ONLINE_COUNT.get();
    }
}
