import { EventEmitter } from 'eventemitter3';
import { initWs } from '../../ws-adapter/index.ts';
import type { ClientOptions } from 'ws';
type WSSOptions = {
  url: string;
  ws?: WebSocket;
  onConnect?: () => void;
  wsOptions?: ClientOptions;
  emitter?: EventEmitter;
};
export class WSServer {
  ws: WebSocket;
  onConnect?: () => void;
  connected: boolean;
  emitter: EventEmitter;
  url: string;
  wsOptions?: ClientOptions;
  constructor(opts: WSSOptions) {
    this.connected = false;
    this.url = opts.url;
    this.wsOptions = opts.wsOptions;
    this.initWs(opts);
  }
  async initWs(opts: WSSOptions) {
    if (opts.ws) {
      this.ws = opts.ws;
    }
    this.emitter = opts.emitter || new EventEmitter();
    this.ws = await initWs(opts.url, opts.wsOptions);
    this.onConnect = opts?.onConnect || (() => {});
    this.ws.onopen = this.onOpen.bind(this);
    this.ws.onmessage = this.onMessage.bind(this);
    this.ws.onerror = this.onError.bind(this);
    this.ws.onclose = this.onClose.bind(this);
  }
  async reconnect() {
    this.ws = await initWs(this.url, this.wsOptions);
    this.ws.onopen = this.onOpen.bind(this);
    this.ws.onmessage = this.onMessage.bind(this);
    this.ws.onerror = this.onError.bind(this);
    this.ws.onclose = this.onClose.bind(this);
  }
  /**
   * 连接成功 ws 事件
   */
  async onOpen() {
    this.connected = true;
    this.onConnect();
    this.emitter.emit('open');
  }
  /**
   * 检查是否连接
   * @returns
   */
  async isConnected() {
    if (this.connected) {
      return true;
    }
    return new Promise((resolve) => {
      this.emitter.once('open', () => {
        resolve(true);
      });
    });
  }
  /**
   * 收到消息 ws 事件
   * @param event
   */
  async onMessage(event: MessageEvent) {
    // console.log('WSS onMessage', event);
    this.emitter.emit('message', event);
  }
  /**
   * ws 错误事件
   * @param event
   */
  async onError(event: Event) {
    console.error('WSS onError');
    this.emitter.emit('error', event);
  }
  /**
   * ws 关闭事件
   * @param event
   */
  async onClose(event: CloseEvent) {
    console.error('WSS onClose');
    this.emitter.emit('close', event);
    this.connected = false;
  }
  /**
   * 关闭 ws 连接
   */
  async close() {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.close();
    }
  }
}
