import {DeviceEventEmitter, NativeModules, Platform} from 'react-native';

let SocketIO = NativeModules.SocketIO;

class Socket {
  constructor(host, config) {
    if (typeof host === 'undefined') {
      throw 'Hello there! Could you please give socket a host, please.';
    }
    if (typeof config === 'undefined') {
      config = {};
    }

    this.sockets = SocketIO;
    this.isConnected = false;
    this.handlers = {};
    this.onAnyHandler = null;

    DeviceEventEmitter.addListener('socketEvent', this._handleEvent.bind(this));

    // Set default handlers
    this.defaultHandlers = {
      connect: e => {
        if (e && e.sid) {
          this.id = e.sid;
        }
        this.isConnected = true;
      },

      disconnect: () => {
        this.isConnected = false;
      },
    };

    // Set initial configuration
    this.host = host;
    this.config = config;
    this.sockets.initialize(host, config);
  }

  _handleEvent(event) {
    if (this.defaultHandlers.hasOwnProperty(event.name)) {
      this.defaultHandlers[event.name](event);
    }
    if (this.handlers.hasOwnProperty(event.name)) {
      const res = event.hasOwnProperty('items') ? event.items[0] : {};
      this.handlers[event.name](res);
    }
    if (this.onAnyHandler) {
      this.onAnyHandler(event);
    }
  }

  hasListeners(eventName) {
    return this.handlers.hasOwnProperty(eventName);
  }

  initialize(config) {
    config = {...this.config, ...config};
    this.disconnect();
    DeviceEventEmitter.removeAllListeners('socketEvent');
    const socket = new Socket(this.host, config);
    Object.keys(this.handlers).map(event => {
      const handler = this.handlers[event];
      socket.on(event, handler);
    });
    socket.connect();
    return socket;
  }

  getId() {
    return this.sockets.getId();
  }

  updateQuery(query) {
    return this.sockets.updateQuery(query);
  }

  connect() {
    this.sockets.connect();
  }

  on(event, handler) {
    this.handlers[event] = handler;
    if (Platform.OS === 'android') {
      this.sockets.on(event);
    }
  }

  onAny(handler) {
    this.onAnyHandler = handler;
  }

  emit(event, ...data) {
    this.sockets.emit(event, data);
  }

  joinNamespace(namespace) {
    this.sockets.joinNamespace(namespace);
  }

  leaveNamespace() {
    this.sockets.leaveNamespace();
  }

  disconnect() {
    this.sockets.disconnect();
  }

  reconnect() {
    this.sockets.reconnect();
  }
}

export default Socket;
