import React from 'react';
import { QRCode } from 'react-qrcode';

import { SessionModal } from './session/SessionModal';
import { SessionButton } from './session/SessionButton';

interface Props {
  i18n: any;
  onClose: any;
  pubKeyToUnpair: string | null;
  pubKey: string | null;
}

interface State {
  currentPubKey: string | null;
  accepted: boolean;
  isListening: boolean;
  success: boolean;
  loading: boolean;
  view:
    | 'default'
    | 'waitingForRequest'
    | 'requestReceived'
    | 'requestAccepted'
    | 'confirmUnpair';
  pubKeyRequests: Array<any>;
  data: Array<any>;
}

export class DevicePairingDialog extends React.Component<Props, State> {
  constructor(props: any) {
    super(props);

    this.closeDialog = this.closeDialog.bind(this);
    this.onKeyUp = this.onKeyUp.bind(this);
    this.startReceivingRequests = this.startReceivingRequests.bind(this);
    this.stopReceivingRequests = this.stopReceivingRequests.bind(this);
    this.getPubkeyName = this.getPubkeyName.bind(this);

    this.state = {
      currentPubKey: this.props.pubKey,
      accepted: false,
      isListening: false,
      success: false,
      loading: true,
      view: 'default',
      pubKeyRequests: [],
      data: [],
    };
  }

  componentDidMount() {
    this.getSecondaryDevices();
  }

  private async getSecondaryDevices() {
    const secondaryDevices = await window.libloki.storage.getSecondaryDevicesFor(
      this.state.currentPubKey
    );
    this.setState({
      data: secondaryDevices,
      loading: false,
    });
  }

  public render() {
    const { i18n } = this.props;

    const newData = [
      '053e18835c106a5f9f463a44a9d7ff9a26281d529285a047bd969cfc59d4ab8607',
      '053e18835c106a5f9f463a44a9d7ff9a26281d529285a047bd969cfc59d4ab8604',
    ];
    setTimeout(() => {
      this.setState({
        data: newData,
      });
    }, 2000);

    return (
      <>
        {!this.state.loading ? (
          <SessionModal
            title={i18n('pairedDevices')}
            onOk={() => null}
            onClose={this.closeDialog}
          >
            {this.state.view === 'waitingForRequest' ? (
              <div className="session-modal__centered">
                <h3>{i18n('waitingForDeviceToRegister')}</h3>
                <small className="text-subtle">
                  {i18n('pairNewDevicePrompt')}
                </small>
                <div className="spacer-lg" />

                <div id="qr">
                  <QRCode value={window.textsecure.storage.user.getNumber()} />
                </div>

                <div className="spacer-lg" />
                <div className="session-modal__button-group__center">
                  <SessionButton
                    text={i18n('cancel')}
                    onClick={this.stopReceivingRequests}
                  />
                </div>
              </div>
            ) : (
              <>
                {this.state.data.length == 0 ? (
                  <div className="session-modal__centered">
                    <div>{i18n('noPairedDevices')}</div>
                  </div>
                ) : (
                  <div className="session-modal__centered">
                    {this.state.data.map((pubKey: any) => {
                      const pubKeyInfo = this.getPubkeyName(pubKey);
                      const isFinalItem =
                        this.state.data[this.state.data.length - 1] === pubKey;

                      return (
                        <div key={pubKey}>
                          <p>
                            {pubKeyInfo.deviceAlias}
                            <br />
                            <span className="text-subtle">
                              Pairing Secret:
                            </span>{' '}
                            {pubKeyInfo.secretWords}
                          </p>
                          {!isFinalItem ? (
                            <hr className="text-soft fullwidth" />
                          ) : null}
                        </div>
                      );
                    })}
                  </div>
                )}

                <div className="spacer-lg" />
                <div className="session-modal__button-group__center">
                  <SessionButton
                    text={i18n('pairNewDevice')}
                    onClick={this.startReceivingRequests}
                  />
                </div>
              </>
            )}
          </SessionModal>
        ) : null}
      </>
    );
  }

  private showView(
    view?:
      | 'default'
      | 'waitingForRequest'
      | 'requestReceived'
      | 'requestAccepted'
      | 'confirmUnpair'
  ) {
    if (!view) {
      this.setState({
        view: 'default',
      });

      return;
    }

    this.setState({ view });
  }

  private startReceivingRequests() {
    this.setState({
      isListening: true,
    });

    this.showView('waitingForRequest');

    //TESTING
    //TESTING
    //TESTING
    setTimeout(() => {
      this.setState({
        accepted: true,
        success: true,
      });
    }, 3000);
  }

  private getPubkeyName(pubKey: string | null) {
    if (!pubKey) {
      return {};
    }

    const secretWords = window.mnemonic.pubkey_to_secret_words(pubKey);
    const conv = window.ConversationController.get(this.state.currentPubKey);
    const deviceAlias = conv ? conv.getNickname() : 'Unnamed Device';
    return { deviceAlias, secretWords };
  }

  private stopReceivingRequests() {
    if (this.state.success) {
      const deviceAlias = this.getPubkeyName(this.state.currentPubKey)[
        'deviceAlias'
      ];
      const conv = window.ConversationController.get(this.state.currentPubKey);
      if (conv) {
        conv.setNickname(deviceAlias);
      }
    }

    this.showView();
  }

  private requestReceived(secondaryDevicePubKey: string | EventHandlerNonNull) {
    // FIFO: push at the front of the array with unshift()
    this.state.pubKeyRequests.unshift(secondaryDevicePubKey);
    if (!this.state.currentPubKey) {
      this.nextPubKey();

      this.showView('requestReceived');
    }
  }

  allowDevice() {
    this.setState({
      accepted: true,
    });
    window.Whisper.trigger(
      'devicePairingRequestAccepted',
      this.state.currentPubKey,
      (errors: any) => this.transmisssionCB(errors)
    );
    this.showView();
  }

  transmisssionCB(errors: any) {
    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.setState({
        success: true,
      });
    } else {
      // this.$('.transmissionStatus').text(errors);
      // this.$('.requestAcceptedView .ok').show();
    }
  }

  skipDevice() {
    window.Whisper.trigger(
      'devicePairingRequestRejected',
      this.state.currentPubKey
    );
    this.nextPubKey();
    this.showView();
  }

  nextPubKey() {
    // FIFO: pop at the back of the array using pop()
    const pubKeyRequests = this.state.pubKeyRequests;
    this.setState({
      currentPubKey: pubKeyRequests.pop(),
    });
  }

  private onKeyUp(event: any) {
    switch (event.key) {
      case 'Esc':
      case 'Escape':
        this.closeDialog();
        break;
      default:
    }
  }

  private closeDialog() {
    window.removeEventListener('keyup', this.onKeyUp);
    this.stopReceivingRequests();
    this.props.onClose();
  }
}