import { director, EventTarget } from "cc";
import { _decorator, Component, Node } from "cc";
import {
  PogWebsocketListener as IWebsocketMessage,
  PogWebsocket,
} from "./PogWebsocket";
const { ccclass, property } = _decorator;

export class WsResponse {
  protocolId: number;
  requestId: number;
  code: number;
  success: boolean;
  data: any;
  msg: string;
}

export class WsRequest {
  requestId: number;
  protocolId: number;
  data: any;
  public static create(protocolId: number): WsRequest {
    let msg = new WsRequest();
    msg.protocolId = protocolId;
    msg.requestId = Math.floor(Math.random() * 1000000);
    msg.requestId = 2;
    return msg;
  }

  public setData(data: any): WsRequest {
    this.data = data;
    return this;
  }

  public async send() {
    let data = JSON.stringify(this);
    await WS.ins.send(data);
  }
}

@ccclass("WS")
export class WS extends Component implements IWebsocketMessage {
  OnMessage(data: any): void {
    // console.warn("onMessage", typeof data.data, data.data);

    if ("pong" == data) {
      return;
    }

    let msg: WsResponse = JSON.parse(data.data);

    this._e.emit("" + msg.protocolId, msg);
  }
  init() {}

  reconnect() {
    if (this.pogWebsocket) {
      try {
        this.pogWebsocket.close();
      } catch (e) {
        console.error(e);
      }
    }
    this.connect(this._url, this._token);
  }

  private _url: string = "";
  private _token: string = "";
  public async connect(url: string, token: string) {
    this._url = url;
    this._token = token;
    return new Promise((resolve) => {
      try {
        let full_url = `${url}?accessToken=${token}`;
        this.pogWebsocket = PogWebsocket.create(full_url, this);
        resolve(true);
      } catch (e) {
        console.error(e);
        resolve(false);
      }
    });
  }
  private static _ins: WS;
  private pogWebsocket: PogWebsocket;

  public static get ins(): WS {
    return (this._ins ??= new WS());
  }

  private _dt: number = 0;

  public update(dt: number) {
    this._dt += dt;
    if (this._dt > 5) {
      this._dt = 0;
      if (this.pogWebsocket) {
        this.pogWebsocket.ping();
      }
    }
  }

  public async send(msg: any) {
    console.log("send", msg);
    for (let i = 0; i < 3; i++) {
      if (!this.pogWebsocket.connected) {
        await new Promise((resolve) => setTimeout(resolve, 500));
      }
    }
    return await this.pogWebsocket.send(msg);
  }

  public close() {
    this.pogWebsocket.close();
  }

  private _e: EventTarget;
  protected onLoad(): void {
    WS._ins = this;
    this._e = new EventTarget();
    this.node.parent = null;
    director.getScene().addChild(this.node);
    director.addPersistRootNode(this.node);
  }

  public on(
    protocolId: number,
    handler: (...args: any[]) => void,
    target: any
  ) {
    this._e.on("" + protocolId, handler, target);
  }

  public off(
    protocolId: number,
    handler: (...args: any[]) => void,
    target: any
  ) {
    this._e.off("" + protocolId, handler, target);
  }

  protected onDestroy(): void {
    //
    console.log("WS onDestroy");
  }
}
