/* global
  Whisper,
  i18n,
  libloki,
  textsecure,
  ConversationController,
  $,
  QRCode,
*/

// eslint-disable-next-line func-names
(function() {
  'use strict';

  window.Whisper = window.Whisper || {};

  Whisper.DevicePairingDialogView = Whisper.View.extend({
    className: 'loki-dialog device-pairing-dialog modal',
    templateName: 'device-pairing-dialog',
    initialize() {
      this.pubKeyRequests = [];
      this.reset();
      this.render();
      this.showView();
      this.qr = new QRCode(this.$('#qr')[0], {
        correctLevel: QRCode.CorrectLevel.L,
      });
      this.qr.makeCode(textsecure.storage.user.getNumber());
    },
    reset() {
      this.pubKey = null;
      this.accepted = false;
      this.isListening = false;
      this.pubKeyToUnpair = null;
      this.success = false;
    },
    events: {
      'click #startPairing': 'startReceivingRequests',
      'click #close': 'close',
      'click .waitingForRequestView .cancel': 'stopReceivingRequests',
      'click .requestReceivedView .skip': 'skipDevice',
      'click #allowPairing': 'allowDevice',
      'click .requestAcceptedView .ok': 'stopReceivingRequests',
      'click .confirmUnpairView .cancel': 'stopReceivingRequests',
      'click .confirmUnpairView .unpairDevice': 'confirmUnpairDevice',
    },
    render_attributes() {
      return {
        defaultTitle: i18n('pairedDevices'),
        waitingForRequestTitle: i18n('waitingForDeviceToRegister'),
        requestReceivedTitle: i18n('devicePairingReceived'),
        requestAcceptedTitle: i18n('devicePairingAccepted'),
        startPairingText: i18n('pairNewDevice'),
        cancelText: i18n('cancel'),
        unpairDevice: i18n('unpairDevice'),
        closeText: i18n('close'),
        skipText: i18n('skip'),
        okText: i18n('ok'),
        allowPairingText: i18n('allowPairing'),
        confirmUnpairViewTitle: i18n('confirmUnpairingTitle'),
      };
    },
    startReceivingRequests() {
      this.trigger('startReceivingRequests');
      this.isListening = true;
      this.showView();
    },
    stopReceivingRequests() {
      if (this.success) {
        const deviceAlias = this.$('#deviceAlias')[0].value.trim();
        const conv = ConversationController.get(this.pubKey);
        if (conv) {
          conv.setNickname(deviceAlias);
        }
      }
      this.trigger('stopReceivingRequests');
      this.reset();
      this.showView();
    },
    requestReceived(secondaryDevicePubKey) {
      // FIFO: push at the front of the array with unshift()
      this.pubKeyRequests.unshift(secondaryDevicePubKey);
      if (!this.pubKey) {
        this.nextPubKey();
        this.showView('requestReceived');
      }
    },
    allowDevice() {
      this.accepted = true;
      this.trigger('devicePairingRequestAccepted', this.pubKey, errors =>
        this.transmisssionCB(errors)
      );
      this.showView();
    },
    transmisssionCB(errors) {
      if (!errors) {
        this.$('.transmissionStatus').text(i18n('provideDeviceAlias'));
        this.$('#deviceAliasView').show();
        this.$('#deviceAlias').on('input', e => {
          if (e.target.value.trim()) {
            this.$('.requestAcceptedView .ok').removeAttr('disabled');
          } else {
            this.$('.requestAcceptedView .ok').attr('disabled', true);
          }
        });
        this.$('.requestAcceptedView .ok').show();
        this.$('.requestAcceptedView .ok').attr('disabled', true);
        this.success = true;
      } else {
        this.$('.transmissionStatus').text(errors);
        this.$('.requestAcceptedView .ok').show();
      }
    },
    skipDevice() {
      this.trigger('devicePairingRequestRejected', this.pubKey);
      this.nextPubKey();
      this.showView();
    },
    nextPubKey() {
      // FIFO: pop at the back of the array using pop()
      this.pubKey = this.pubKeyRequests.pop();
    },
    async confirmUnpairDevice() {
      this.trigger('deviceUnpairingRequested', this.pubKeyToUnpair);
      this.reset();
      this.showView();
    },
    requestUnpairDevice(pubKey) {
      this.pubKeyToUnpair = pubKey;
      this.showView();
    },
    getPubkeyName(pubKey) {
      const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey);
      const conv = ConversationController.get(pubKey);
      const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device';
      return `${deviceAlias} (pairing secret: <i>${secretWords}</i>)`;
    },
    async showView() {
      const defaultView = this.$('.defaultView');
      const waitingForRequestView = this.$('.waitingForRequestView');
      const requestReceivedView = this.$('.requestReceivedView');
      const requestAcceptedView = this.$('.requestAcceptedView');
      const confirmUnpairView = this.$('.confirmUnpairView');
      if (this.pubKeyToUnpair) {
        defaultView.hide();
        requestReceivedView.hide();
        waitingForRequestView.hide();
        requestAcceptedView.hide();
        confirmUnpairView.show();
        const name = this.getPubkeyName(this.pubKeyToUnpair);
        this.$('.confirmUnpairView #pubkey').html(name);
      } else if (!this.isListening) {
        requestReceivedView.hide();
        waitingForRequestView.hide();
        requestAcceptedView.hide();
        confirmUnpairView.hide();

        const ourPubKey = textsecure.storage.user.getNumber();
        defaultView.show();
        const pubKeys = await libloki.storage.getSecondaryDevicesFor(ourPubKey);
        this.$('#pairedPubKeys').empty();
        if (pubKeys && pubKeys.length > 0) {
          this.$('#startPairing').attr('disabled', true);
          pubKeys.forEach(x => {
            const name = this.getPubkeyName(x);
            const li = $('<li>').html(name);
            if (window.lokiFeatureFlags.multiDeviceUnpairing) {
              const link = $('<a>')
                .text('Unpair')
                .attr('href', '#');
              link.on('click', () => this.requestUnpairDevice(x));
              li.append(' - ');
              li.append(link);
            }
            this.$('#pairedPubKeys').append(li);
          });
        } else {
          this.$('#startPairing').removeAttr('disabled');
          this.$('#pairedPubKeys').append('<li>No paired devices</li>');
        }
      } else if (this.accepted) {
        defaultView.hide();
        requestReceivedView.hide();
        waitingForRequestView.hide();
        requestAcceptedView.show();
      } else if (this.pubKey) {
        const secretWords = window.mnemonic.pubkey_to_secret_words(this.pubKey);
        this.$('.secretWords').text(secretWords);
        requestReceivedView.show();
        waitingForRequestView.hide();
        requestAcceptedView.hide();
        defaultView.hide();
      } else {
        waitingForRequestView.show();
        requestReceivedView.hide();
        requestAcceptedView.hide();
        defaultView.hide();
      }
    },
    close() {
      this.remove();
      this.qr.clear();
      if (this.pubKey && !this.accepted) {
        this.trigger('devicePairingRequestRejected', this.pubKey);
      }
      this.trigger('close');
    },
  });
})();