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

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;

    this.deviceEventSubscription = 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.sockets.initialize(host, config);
  }

  debounceHandler = debounce(1000, true, event => {
    console.warn(event.name);
    const res = event.hasOwnProperty('items') ? event.items[0] : {};
    this.handlers[event.name](res);
  });

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

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

  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;
