'use strict';

type IXmppClient = any;
const XmppClient: IXmppClient = require('node-xmpp-client');

import { EventEmitter } from 'events';

export default class XmppHelper extends EventEmitter {
  private _identity: string;
  private _connected: boolean;
  private _XMPP_HOST: string;
  private _JID_SUFFIX: string;
  private _XMPP_INCOMING_EVENT: string;
  private _client: IXmppClient;

  constructor (params: { identity: string; password: string }, constants: { XMPP_HOST: string; JID_SUFFIX: string; XMPP_INCOMING_EVENT: string }) {
    super();

    this._identity  = params.identity;
    this._connected = false;

    this._XMPP_HOST = constants.XMPP_HOST;
    this._JID_SUFFIX = constants.JID_SUFFIX;
    this._XMPP_INCOMING_EVENT = constants.XMPP_INCOMING_EVENT;

    var options = {
      jid:       this._JID(),
      password:  params.password,
      reconnect: true,
      autostart: false
    };

    this._client = new XmppClient(options);
    this._initClient();
  }

  get connected (): boolean { return this._connected; }

  disconnect (): void {
    this._connected = false;
    this._client.end();
  }

  connect (): void {
    this._client.connect();
    this._subscribe();
    this._client.connection.socket.setTimeout(0);
    this._client.connection.socket.setKeepAlive(true, 10000);
  }

  _subscribe (): void {
    var message: string = `
      <iq type='set'
          from='${this._JID()}'
          to='${this._XMPP_HOST}'
          id='sub1'>
        <pubsub xmlns='http://jabber.org/protocol/pubsub'>
          <subscribe
              node='finesse/api/User/${this._identity}'
              jid=${this._JID()}/>
        </pubsub>
      </iq>`;
    this._client.send(message);
  }

  _JID (): string {
    return `${this._identity}${this._JID_SUFFIX}`;
  }

  _initClient (): void {
    var identity = this._identity;

    this._client.on('online', () => {
      console.log(`${identity} connected`);
      this._connected = true;
      this._client.send('<presence/>');
    });

    this._client.on('offline', () => {
      console.log(`${identity} disconnected`);
    });

    this._client.on('stanza', stanza => {
      this.emit(this._XMPP_INCOMING_EVENT, stanza);
    });

    this._client.on('connect', () => {
      console.log(`Client is connected (${identity})`);
    });

    this._client.on('reconnect', () => {
      console.log(`Client reconnects (${identity})`);
    });

    this._client.on('disconnect', e => {
      this._connected = false;
      console.log(`Client is disconnected (${identity})`, this._client.connection.reconnect, e);
    });

    this._client.on('error', e => {
      console.error('Error', e);
    });
  }
};
