import { EventEmitter } from 'eventemitter3';
import { initWs } from '../ws/index.ts';
import type { ClientOptions } from 'ws';
export type WSSOptions = {
  url: string;
  ws?: WebSocket;
  onConnect?: () => void;
  wsOptions?: ClientOptions;
  emitter?: EventEmitter;
};
interface WSServerInterface {
  isComplated(type: string, endType?: string): Promise<boolean>;
  start(): Promise<void>;
}
export class WSServer implements WSServerInterface {
  ws: WebSocket;
  onConnect?: () => void;
  connected: boolean;
  connecting: boolean = false;
  emitter: EventEmitter;
  url: string;
  wsOptions?: ClientOptions;
  constructor(opts: WSSOptions) {
    this.connected = false;
    this.url = opts.url;
    this.wsOptions = opts.wsOptions;
    this.emitter = opts?.emitter || new EventEmitter();
    this.onConnect = opts?.onConnect || (() => { });
    this.initWs();
  }
  async initWs(opts?: WSSOptions) {
    if (opts?.ws) {
      this.ws = opts.ws;
    }
    if (opts?.emitter) {
      this.emitter = opts.emitter;
    }
    if (opts?.onConnect) {
      this.onConnect = opts.onConnect;
    }
    if (opts?.emitter) {
      this.emitter = opts.emitter;
    }
    this.connecting = true;

    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);
  }
  async reconnect(opts?: { timeout?: number }) {
    if (this.connected || this.connecting) {
      return;
    }
    this.connecting = true;
    const timeout = opts?.timeout || 0;
    if (timeout > 0) {
      await new Promise((resolve) => setTimeout(resolve, timeout));
    }

    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);
  }

  async start() {
    // do nothing
  }
  /**
   * 连接成功 ws 事件
   */
  async onOpen() {
    this.connected = true;
    this.connecting = false;
    this?.onConnect?.();
    this.emitter.emit('open');
  }
  /**
   * 检查是否连接
   * @returns
   */
  async isConnected() {
    if (this.connected) {
      return true;
    }
    return new Promise((resolve) => {
      const timeout = setTimeout(() => {
        resolve(false);
      }, 5000);
      this.emitter.once('open', () => {
        clearTimeout(timeout);
        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) {
    this.emitter.emit('close', event);
    this.connected = false;
    setTimeout(() => {
      this.emitter.removeAllListeners();
    }, 100);
    const { code } = event;
    if (typeof code === 'number' && code !== 0) {
      this.reconnect({ timeout: 10000 });
    }
  }
  /**
   * 检查并连接 ws
   * @returns 
   */
  async checkConnected() {
    const connecting = this.connecting
    if (connecting) {
      return this.isConnected();
    }
    if (!this.connected) {
      await this.reconnect();
      return this.isConnected();
    }
    return true;
  }
  /**
   * 关闭 ws 连接
   */
  async close() {
    if (this.ws.readyState === WebSocket.OPEN) {
      this.ws.close();
    }
  }

  async isComplated(type: string, endType = '') {
    if (type === endType) {
      return true;
    }
    return false;
  }

  /**
   * 生成指定时长的静音 WAV 音频缓冲区
   * @param durationSeconds 静音时长（秒）
   * @returns WAV 音频缓冲区
   */
  generateSilence(durationSeconds: number): Buffer {
    const sampleRate = 16000; // 采样率 16kHz
    const bitDepth = 16; // 位深 16bit
    const channels = 1; // 单声道
    const duration = durationSeconds; // 时长

    const samplesPerChannel = sampleRate * duration;
    const bytesPerSample = bitDepth / 8;
    const blockAlign = channels * bytesPerSample;
    const byteRate = sampleRate * blockAlign;
    const dataSize = samplesPerChannel * blockAlign;
    const fileSize = 36 + dataSize;

    // 创建 WAV 文件头
    const header = Buffer.alloc(44);
    let offset = 0;

    // RIFF 标识
    header.write('RIFF', offset); offset += 4;
    header.writeUInt32LE(fileSize, offset); offset += 4;
    header.write('WAVE', offset); offset += 4;

    // fmt 子块
    header.write('fmt ', offset); offset += 4;
    header.writeUInt32LE(16, offset); offset += 4; // fmt 块大小
    header.writeUInt16LE(1, offset); offset += 2; // PCM 格式
    header.writeUInt16LE(channels, offset); offset += 2; // 声道数
    header.writeUInt32LE(sampleRate, offset); offset += 4; // 采样率
    header.writeUInt32LE(byteRate, offset); offset += 4; // 字节率
    header.writeUInt16LE(blockAlign, offset); offset += 2; // 块对齐
    header.writeUInt16LE(bitDepth, offset); offset += 2; // 位深

    // data 子块
    header.write('data', offset); offset += 4;
    header.writeUInt32LE(dataSize, offset);

    // 创建静音数据（全为0）
    const silenceData = Buffer.alloc(dataSize);

    // 合并头部和数据
    return Buffer.concat([header, silenceData]);
  }
  async sendBlank(buffer?: Buffer) {
    const isConnected = await this.checkConnected();
    if (!isConnected) {
      this.reconnect({ timeout: 1000 });
      return;
    }
    if (buffer) {
      this.ws.send(buffer);
      return;
    }
    // 生成一个 2 秒静音
    const blankBuffer = this.generateSilence(2);
    this.ws.send(blankBuffer);
  }
}
