// eslint-disable-next-line import/no-unresolved
import { NativeEventEmitter } from 'react-native';
import base64 from '../../../utils/base64';
import modeManager from '../common/modeManager';

let nativeWebSocket = null;
function getNativeWebSocket() {
  if (!nativeWebSocket) {
    nativeWebSocket = modeManager.getModule('MiniAppWebSocket');
  }
  return nativeWebSocket || {};
}

let nextWebSocketId = 0;

export default class Socket {
  constructor(opt) {
    this._reset();
    this._eventEmitter = new NativeEventEmitter(getNativeWebSocket());
    this._socketId = nextWebSocketId++;
    this._initEvents();
    getNativeWebSocket().connect(opt, this._socketId);
  }

  _reset() {
    this.onopen = () => { };
    this.onclose = () => { };
    this.onerror = () => { };
    this.onmessage = () => { };
  }

  _initEvents() {
    const onOpen = this._eventEmitter.addListener(modeManager.getName("kMiniAppWebSocketOpen"), evt => {
      if (parseInt(evt.id) === this._socketId) this.onopen(evt);
    });
    const onClose = this._eventEmitter.addListener(modeManager.getName("kMiniAppWebSocketClosed"), evt => {
      if (parseInt(evt.id) === this._socketId) this.onclose(evt);
    });
    const onFailed = this._eventEmitter.addListener(modeManager.getName("kMiniAppWebSocketFailed"), evt => {
      if (parseInt(evt.id) === this._socketId) this.onerror(evt);
    });
    const onMessage = this._eventEmitter.addListener(modeManager.getName("kMiniAppWebSocketMessage"), evt => {
      if (parseInt(evt.id) !== this._socketId) return;
      if (evt.data && evt.cmd == 3) {
        evt.data = base64.decode(evt.data);
      }
      this.onmessage(evt);
    });
    this._subscriptions = [onOpen, onClose, onFailed, onMessage];
  }

  /**
   * 发送数据
   * @param {any} data 
   */
  send(data) {
    if (typeof data === "string") {
      return getNativeWebSocket().send(data, this._socketId);
    }

    if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
      return getNativeWebSocket().sendBinary(base64.encode(data), this._socketId);
    }

    throw new Error('Unsupported data type');
  }

  /**
   * 断开链接
   * @param {number} code 
   * @param {string} reason 
   */
  close(code, reason) {
    getNativeWebSocket().close(code, reason, this._socketId);
  }

  /**
   * 销毁
   */
  destroy() {
    this._subscriptions.map(e => e.remove());
    this._reset();
  }
}
