package com.njzscloud.common.ws.support;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.core.ex.ExceptionMsg;
import com.njzscloud.common.core.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;


/**
 * websocket 处理器<br/>
 * 不支持分片消息<br/>
 * 支持文本、二进制信息
 */
@Slf4j
public class ImpartialWebSocketHandler extends AbstractWebSocketHandler {

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Wsdoor wsdoor = Wsdoor.of(session);
        String cid = wsdoor.getCid();
        Long uid = wsdoor.getUid();
        wsdoor.send(new WsMsg()
                .setEvent("connected")
                .setData(R.success(
                        MapUtil.builder()
                                .put("uid", uid)
                                .put("cid", cid)
                                .build()
                        , "连接成功")));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        Wsdoor wsdoor = Wsdoor.of(session);
        WsMsg wsMsg = WsMsg.of(wsdoor, message);

        if (wsMsg == null
                || StrUtil.isBlank(wsMsg.getAction())
                || StrUtil.isBlank(wsMsg.getEvent())) {
            wsdoor.send(new WsMsg().setEvent("error")
                    .setData(R.failed(ExceptionMsg.CLI_ERR_MSG, "消息格式错误")));
            session.close();
            return;
        }
        String action = wsMsg.getAction();

        if (!Websocket.ACTION_PUBLISH.equals(action)
                && !Websocket.ACTION_PING.equals(action)
                && !Websocket.ACTION_UNSUBSCRIBE.equals(action)
                // && !Websocket.ACTION_PONG.equals(action)
                && !Websocket.ACTION_SUBSCRIBE.equals(action)
        ) {
            wsdoor.send(new WsMsg().setEvent("error")
                    .setData(R.failed(ExceptionMsg.CLI_ERR_MSG, "消息格式错误")));
            session.close();
            return;
        }

        String event = wsMsg.getEvent();
        if (Websocket.ACTION_PUBLISH.equals(action)) {
            Websocket.publish(wsMsg);
        } else if (Websocket.ACTION_SUBSCRIBE.equals(action)) {
            WsMsg.User from = wsMsg.getFrom();
            log.info("用户Id：{}，客户端Id：{}，订阅：{}", from.getUid(), from.getCid(), event);
            Websocket.subscribe(event, wsdoor);
        } else if (Websocket.ACTION_UNSUBSCRIBE.equals(action)) {
            WsMsg.User from = wsMsg.getFrom();
            log.info("用户Id：{}，客户端Id：{}，取消订阅：{}", from.getUid(), from.getCid(), event);
            Websocket.unsubscribe(event, wsdoor);
        } else {
            wsdoor.send(new WsMsg().setAction(Websocket.ACTION_PONG));
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        Wsdoor wsdoor = Wsdoor.of(session);
        String cid = wsdoor.getCid();
        Long uid = wsdoor.getUid();
        log.error("连接失败: {} {}", cid, uid, exception);
        Websocket.unsubscribe(wsdoor);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        Wsdoor wsdoor = Wsdoor.of(session);
        String cid = wsdoor.getCid();
        Long uid = wsdoor.getUid();
        log.info("连接关闭: {} {} {}", cid, uid, closeStatus);
        Websocket.unsubscribe(wsdoor);
    }
}
