import * as websocket from "ws";
import { Server } from 'http';
import * as handler from "./class/websockethandler";

export default class WSSignaling {
  server: Server;
  wss: websocket.Server;

  /**
   * 构造函数，初始化WebSocket信令服务器
   * @param server HTTP服务器实例
   * @param mode 通信模式（public或private）
   */
  constructor(server: Server, mode: string) {
    // 保存服务器实例
    this.server = server;
    // 创建WebSocket服务器
    this.wss = new websocket.Server({ server });
    // 重置处理器，设置通信模式
    handler.reset(mode);

    /**
     * 监听WebSocket连接事件
     * @param ws WebSocket连接实例
     */
    this.wss.on('connection', (ws: WebSocket) => {
      // 添加新的WebSocket连接到处理器
      handler.add(ws);
      //handler.AddHeartbeat(ws);
      /**
       * 监听连接关闭事件
       */
      ws.onclose = (): void => {
        // 从处理器中移除关闭的连接
        handler.remove(ws);
        //handler.RemoveHeartbeat(ws);
      };

      /**
       * 监听消息事件
       * @param event 消息事件对象
       */
      ws.onmessage = (event: MessageEvent): void => {
        // 消息类型说明：
        // 1. connect, disconnect 消息格式：
        //    { type: "connect", connectionId: "连接ID" }
        //    { type: "disconnect", connectionId: "连接ID" }
        // 2. offer, answer, candidate 消息格式：
        //    {
        //      type: "offer",
        //      data: {
        //        from: "发送方连接ID",
        //        to: "接收方连接ID",
        //        data: "信令数据"
        //      }
        //    }
        // 3. broadcast 消息格式：
        //    {
        //      type: "broadcast",
        //      message: "广播消息内容",
        //      targetConnectionId: "目标连接ID（可选）"
        //    }

        // 解析消息数据
        const msg = JSON.parse(event.data);
        // 检查消息是否有效
        if (!msg || !this) {
          return;
        }

        // 打印接收到的消息
        console.log(msg);

        // 根据消息类型处理
        switch (msg.type) {
          case "connect":
            handler.onConnect(ws, msg.connectionId);
            break;
          case "disconnect":
            handler.onDisconnect(ws, msg.connectionId);
            break;
          case "offer":
            if (msg.participantId !== undefined) msg.data.participantId = msg.participantId;
            handler.onOffer(ws, msg.data);
            break;
          case "answer":
            if (msg.participantId !== undefined) msg.data.participantId = msg.participantId;
            handler.onAnswer(ws, msg.data);
            break;
          case "candidate":
            if (msg.participantId !== undefined) msg.data.participantId = msg.participantId;
            handler.onCandidate(ws, msg.data);
            break;
          case "ping":
            ws.send(JSON.stringify({ type: "pong" }));
            break;
          case "pong":
            (ws as any).lastActivity = Date.now();
            break;
          case "broadcast":
            handler.onBroadcast(ws, msg.data);
            break;
          case 'call-request':
            handler.onCallConnectionId(ws, msg.data);
            break;
          case 'on-message':
            if (msg.from) msg.data.connectionId = msg.from;
            handler.onMessage(ws, msg.data);
            break;
          default:
            break;
        }
      };
    });
  }
}
