import messager from '../common/messager';

import topicListener from '../common/topicListener';
import EventManager from '../../../manager/eventManager';
import base64Util from '../../../utils/base64';
import strRender from '../../../utils/strRender';

/**
 * 初始化监听 wsMessage 消息
 */
const wsEventer = new EventManager();
topicListener.on('wsMessage', ({ msg }) => {
  const { event, data } = msg || {};

  // 特殊处理
  if (data && event === 'message') {
    const { type, base64 } = data;
    data.data = type === 'string' ? base64 : base64Util.decode(base64);
  }

  wsEventer.emit(`ws.${event}`, data);
});

export default class Socket {
  constructor(opt) {
    this._reset();
    this._initEvents(opt);
  }

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

  _initEvents(opt) {
    // 建立连接，获取id
    messager.dispatch('wsConnect', opt).then(({ wsId, binaryType, protocol }) => {
      this._wsId = wsId;
      this.binaryType = binaryType;
      this.protocol = protocol;
    }).catch(err => this.onerror(err));

    wsEventer.on('ws.open', ({ wsId }) => {
      if (wsId === this._wsId) this.onopen();
    });

    wsEventer.on('ws.close', ({ wsId, code, reason, wasClean }) => {
      if (wsId === this._wsId) this.onclose({ code, reason, wasClean });
    });

    wsEventer.on('ws.error', ({ wsId, message }) => {
      if (wsId === this._wsId) this.onerror(new Error(message));
    });

    wsEventer.on('ws.message', ev => {
      if (ev && ev.wsId === this._wsId) this.onmessage(ev);
    });
  }

  /**
   * 发送数据
   * @param {any} data 
   */
  send(data) {
    const msg = strRender.getWSMessage(data);
    if (!msg) {
      this.onerror(new Error('send invalid data'));
    }

    const isString = typeof msg === 'string';
    const param = {
      wsId: this._wsId,
      type: isString ? 'string' : 'arraybuffer',
      base64: isString ? msg : base64Util.encode(msg)
    };
    messager.dispatch('wsSend', param).catch(err => this.onerror(err));
  }

  /**
   * 断开链接
   * @param {number} code 
   * @param {string} reason 
   */
  close(code, reason) {
    messager.dispatch('wsClose', { wsId: this._wsId, code, reason }).catch(err => this.onerror(err));
  }

  /**
   * 销毁
   */
  destroy() {
    this._reset();
  }
}
