/**连接参数类型 */
export type OptionsType = {
  /**
   * 线路工作服务地址
   *
   * self.onmessage = error => {} - 接收消息
   *
   * self.postMessage() -回复消息
   */
  url: string;
  /**message事件的回调函数 */
  onmessage: (data: any) => void;
  /**error事件的回调函数 */
  onerror: Function;
  /**close事件的回调函数 */
  onclose?: (code: number) => void;
};

/**
 * Web Worker 使用方法
 *
 * import { WK, OptionsType } from '@/plugins/wk-worker';
 *
 * const wk = new WK();
 *
 * 创建连接
 * const options: OptionsType = { };
 * wk.connect(options);
 *
 * 手动关闭
 * wk.close();
 */
export class WK {
  /**wk 实例 */
  private wk: Worker | null = null;
  /**wk 连接参数 */
  private options: OptionsType | null = null;

  /**
   * 构造函数
   * @param {object} params 构造函数参数
   */
  constructor(options?: OptionsType) {
    if (!window.Worker) {
      // 检测浏览器支持
      console.error('Sorry! Browser does not support Web Workers');
      return;
    }
    options && this.connect(options);
  }

  /**
   * 创建链接
   * @param {object} options 连接参数
   */
  public connect(options: OptionsType) {
    this.options = options;
    try {
      const wk = new Worker(options.url);
      // 用于收到来自其消息时的回调函数。
      wk.onmessage = ev => {
        // 解析文本消息
        if (ev.type === 'message') {
          try {
            if (typeof options.onmessage === 'function') {
              options.onmessage(ev.data);
            }
          } catch (error) {
            console.error('worker message formatting error', error);
          }
        }
      };
      // 用于发生错误关闭后的回调函数。
      wk.onmessageerror = ev => {
        console.error('worker message error anomaly', ev);

        if (typeof options.onclose === 'function') {
          options.onerror(ev);
        }
      };
      // 用于发生错误后的回调函数。
      wk.onerror = ev => {
        console.error('worker error anomaly', ev);

        if (typeof options.onerror === 'function') {
          options.onerror(ev);
        }
      };
      this.wk = wk;
    } catch (error) {
      if (typeof options.onerror === 'function') {
        options.onerror(error);
      }
    }
  }

  /**
   * 发送消息
   * @param data JSON数据
   * @returns
   */
  public send(data: Record<string, any>): boolean {
    if (!this.wk) {
      console.warn('worker unavailable');
      return false;
    }

    this.wk.postMessage(data);
    return true;
  }

  // 手动关闭会被立即终止
  public close() {
    if (!this.wk) {
      console.warn('worker unavailable');
      return;
    }
    this.wk.terminate();
    // 用于关闭后的回调函数。
    if (this.options && typeof this.options.onclose === 'function') {
      this.options.onclose(1000);
    }
  }
}
