export default class XClient {
  url = "";
  name = "";
  ws = null;
  timeout = 1000 * 5;
  heartbeatDelay = 1000 * 60 * 3;
  reconnectCount = 0;
  onmessage = null;
  hb = 0;

  constructor(
    config,
    onmessage
  ) {
    this.url = config.url;
    this.name = config.name;
    this.ws = new WebSocket(config.url);
    this.timeout = config.timeout || 1000 * 5;

    this.ws.onopen = () => {
      console.log(`[*] ${this.name} 初始化连接成功`);
      this.hb = this.heartbeat();
    };
    this.onmessage = onmessage;
    this.ws.onmessage = onmessage;
    this.ws.onerror = (err) => {
      console.log(`[*] ${this.name} 连接错误`, err);
      this.tryReconnect();
    };
    this.ws.onclose = (e) => {
      console.log(`[*] ${this.name} 连接关闭`);
    };
  }

  heartbeat() {
    if (this.hb) clearInterval(this.hb);
    return setInterval(() => {
      console.log(`${this.name} ping...`);
      if (this.ws.readyState == WebSocket.OPEN) {
        this.ws.send("ping");
      } else {
        clearInterval(this.hb);
        this.tryReconnect();
      }
    }, this.heartbeatDelay);
  }

  tryReconnect() {
    console.log(`[*] ${this.name} 重连中，已尝试:`, this.reconnectCount, "次");
    setTimeout(
      () => {
        if (this.ws.readyState === WebSocket.OPEN) {
          this.reconnectCount = 0;
          console.log(`[*] ${this.name} 已恢复连接，取消重连`);
          return;
        }
        this.reconnectCount++;
        this.ws = new WebSocket(this.url);
        this.ws.onopen = () => {
          console.log(`[*] ${this.name} 重连成功`);
          this.reconnectCount = 0;
          this.hb = this.heartbeat();
        };
        this.ws.onmessage = this.onmessage;
        this.ws.onerror = (err) => {
          console.log(`[*] ${this.name} 重连出错`);
          this.tryReconnect();
        };
        this.ws.onclose = (e) => {
          console.log(`[*] ${this.name} 重连连接关闭`);
        };
      },
      this.reconnectCount == 0 ? 0 : this.timeout
    );
  }

  logStatus() {
    console.log(
      `[*] ${this.name} 重连状态: 连接中`,
      this.ws.readyState == WebSocket.CONNECTING
    );
    console.log(
      `[*] ${this.name} 重连状态: 已连接`,
      this.ws.readyState == WebSocket.OPEN
    );
    console.log(
      `[*] ${this.name} 重连状态: 关闭中`,
      this.ws.readyState == WebSocket.CLOSING
    );
    console.log(
      `[*] ${this.name} 重连状态: 关闭`,
      this.ws.readyState == WebSocket.CLOSED
    );
  }
}
