/*
 * Copyright (c) 2018-2019, FusionAuth, All Rights Reserved
 */
'use strict';

var FusionAuth = FusionAuth || {};
FusionAuth.Admin = FusionAuth.Admin || {};

/**
 * Handles the add and edit Identity Provider form. The row table is managed by the ExpandableTable object.
 *
 * @constructor
 */
FusionAuth.Admin.IdentityProviderForm = function(type) {
  Prime.Utils.bindAll(this);

  switch (type) {
    case 'OpenIDConnect':
      this._setupOpenIdConnect();
      break;
    case 'SAMLv2':
      this._setupSAMLv2();
      break;
    case 'ExternalJWT':
      this._setupJWTType();
      break;
  }

  // For everything except the red headed step child
  if (type !== 'ExternalJWT') {
    this._attachApplicationEvents();
  }
};

FusionAuth.Admin.IdentityProviderForm.constructor = FusionAuth.Admin.IdentityProviderForm;
FusionAuth.Admin.IdentityProviderForm.prototype = {

  /* ===================================================================================================================
   * Private methods
   * ===================================================================================================================*/

  _attachApplicationEvents: function() {
    // Attach override toggles
    Prime.Document.query('.slide-open-toggle').each(function(toggle) {
      toggle.addEventListener('click', this._handleOverrideClick)
    }.bind(this));
  },

  _setupOpenIdConnect: function() {
    new FusionAuth.UI.TextEditor(Prime.Document.queryFirst('textarea[name="domains"]'))
        .withOptions({
          'mode': 'properties',
          'lineNumbers': true,
        })
        .render()
        .setHeight(100);

    this.openIdIssuer = Prime.Document.queryFirst('input[name="identityProvider.oauth2.issuer"]');
    this.useOpenIdDiscovery = Prime.Document.queryById('useOpenIdDiscovery').addEventListener('change', this._handleUserOpenIdDiscoveryChange);

    this.openIdIssuerSlideOpen = this.openIdIssuer.queryUp('.slide-open');
    this.openIdIssuerSlideOpen._open = this.useOpenIdDiscovery.isChecked();
  },

  _setupSAMLv2: function() {
    new FusionAuth.UI.TextEditor(Prime.Document.queryFirst('textarea[name="domains"]'))
        .withOptions({
          'mode': 'properties',
          'lineNumbers': true
        })
        .render()
        .setHeight(100);
  },

  _handleOverrideClick: function(event) {
    Prime.Utils.stopEvent(event);

    var toggle = new Prime.Document.Element(event.currentTarget); // currentTarget is the <a> the event was bound to
    var target = Prime.Document.queryById(toggle.getDataAttribute("expandOpen"));
    var icon = toggle.queryFirst('i.fa');
    if (target.hasClass('open')) {
      icon.removeClass('open');
      new Prime.Effects.SlideOpen(target).toggle();
    } else {
      icon.addClass('open');
      new Prime.Effects.SlideOpen(target).toggle();
    }
  },

  _handleUserOpenIdDiscoveryChange: function() {
    if (this.openIdIssuerSlideOpen._open) {
      this.openIdIssuer.setDisabled(true);
      this.openIdIssuerSlideOpen._open = false;
    } else {
      this.openIdIssuer.setDisabled(false);
      this.openIdIssuerSlideOpen._open = true;
    }
  },

  _setupJWTType: function() {
    this.form = Prime.Document.queryById('identity-provider-form');
    this.addIdentityProvider = this.form.getAttribute('action') === '/admin/identity-provider/add';
    this.domainEditor = new FusionAuth.UI.TextEditor(this.form.queryFirst('textarea[name="domains"]'))
        .withOptions({
          'mode': 'properties',
          'lineNumbers': true,
        });

    // Add Keys
    this.keyTable = Prime.Document.queryById('public-keys-table');
    this.expandableKeyTable = new FusionAuth.UI.ExpandableTable(this.keyTable);

    // View key button
    this.keyTable.addDelegatedEventListener('click', 'a.view-button', this._handleViewKeyClick);

    this.keyDataSet = null;
    Prime.Document.queryById('add-key').addEventListener('click', this._handleAddKeyClick);

    // Add Claims
    this.claimTable = Prime.Document.queryById('claims-map-table');
    this.expandableClaimTable = new FusionAuth.UI.ExpandableTable(this.claimTable);

    this.claimDataSet = null;
    Prime.Document.queryById('add-claim').addEventListener('click', this._handleAddClaimClick);

    new Prime.Widgets.Tabs(Prime.Document.queryFirst('.tabs'))
        .withErrorClassHandling('error')
        .withLocalStorageKey(this.addIdentityProvider ? null : 'settings.identity-provider.external-jwt.tabs')
        .withSelectCallback(this._handleTabSelect)
        .initialize();
  },

  _getDataFromClaimForm: function() {
    var form = this.claimDialog.element.queryFirst('form');
    var data = {};
    data.incomingClaim = form.queryFirst('input[name="incomingClaim"]').getValue();
    data.fusionAuthClaim = form.queryFirst('select[name="fusionAuthClaim"]').getValue();
    return data;
  },

  _getDataFromKeyForm: function() {
    var form = this.keyDialog.element.queryFirst('form');
    var data = {};
    data.keyId = form.queryFirst('input[name="keyId"]').getValue();
    data.encodedKey = form.queryFirst('textarea[name="encodedKey"]').getValue();
    return data;
  },

  _handleAddClaimClick: function(event) {
    Prime.Utils.stopEvent(event);

    this.claimDataSet = null;
    var anchor = new Prime.Document.Element(event.currentTarget);
    this.claimDialog = new Prime.Widgets.AJAXDialog()
        .withCallback(this._handleAddClaimDialogOpenSuccess)
        .withFormHandling(true)
        .withFormErrorCallback(this._handleAddClaimDialogOpenSuccess)
        .withFormSuccessCallback(this._handleAddClaimFormSuccess)
        .open(anchor.getAttribute('href') + '?identityProviderId=' + anchor.getAttribute('identityProviderId'));
  },

  _handleAddKeyClick: function(event) {
    Prime.Utils.stopEvent(event);

    this.keyDataSet = null;
    var anchor = new Prime.Document.Element(event.currentTarget);
    this.keyDialog = new Prime.Widgets.AJAXDialog()
        .withCallback(this._handleAddKeyDialogOpenSuccess)
        .withAdditionalClasses('wide')
        .withFormHandling(true)
        .withFormPreSubmitCallback(this._handleAddKeyPreFormSubmit)
        .withFormSuccessCallback(this._handleAddKeyFormSuccess)
        .open(anchor.getAttribute('href') + '?identityProviderId=' + anchor.getAttribute('identityProviderId'));
  },

  _handleAddClaimDialogOpenSuccess: function(dialog) {
    if (this.claimDataSet !== null) {
      dialog.element.queryFirst('input[name="incomingClaim"]').setValue(this.claimDataSet.incomingClaim);
      dialog.element.queryFirst('select[name="fusionAuthClaim"]').setValue(this.claimDataSet.fusionAuthClaim);
    }

    dialog.element.queryFirst('input[name="incomingClaim"]').focus();
  },

  _handleAddKeyDialogOpenSuccess: function(dialog) {
    if (this.keyDataSet !== null) {
      dialog.element.queryFirst('input[name="keyId"]').setValue(this.keyDataSet.keyId);
      dialog.element.queryFirst('textarea[name="encodedKey"]').setValue(this.keyDataSet.encodedKey);
    }

    this.encodedKeyEditor = new FusionAuth.UI.TextEditor(dialog.element.queryFirst('textarea'))
        .withOptions({
          'mode': 'properties',
          'lineNumbers': true,
          'lineWrapping': false
        }).render();

    // Disable / Enable keyId from toggle, hide placeholder to make it look more 'disabled'
    this.addKeyId = dialog.element.queryFirst('input[name="keyId"]');
    this.addDefaultCheckbox = dialog.element.queryFirst('input[type="checkbox"]');

    this.addKeyId.setAttribute('data-placeholder', this.addKeyId.getAttribute('placeholder'));
    this.addDefaultCheckbox.addEventListener('change', this._toggleKeyIdField);
    // on load set keyId for validation errors
    this._toggleKeyIdField();

    dialog.element.queryFirst('input[type="text"]').focus();
  },

  _handleAddKeyPreFormSubmit: function() {
    // Sync up the text areas since we're submitting the form through AJAX.
    if (this.encodedKeyEditor) {
      this.encodedKeyEditor.sync();
    }
  },

  _handleAddClaimFormSuccess: function() {
    var data = this._getDataFromClaimForm();

    var row = null;
    this.claimTable.query('tbody tr').each(function(r) {
      if (r.getDataSet().incomingClaim === data.incomingClaim) {
        row = r;
      }
    });

    if (row === null) {
      row = this.expandableClaimTable.addRow(data);
    }

    var dataSet = row.getDataSet();
    dataSet.incomingClaim = data.incomingClaim;
    dataSet.fusionAuthClaim = data.fusionAuthClaim;

    this._replaceClaimFieldValues(data);

    // Finally close the dialog
    this.claimDialog.close();
  },

  _handleAddKeyFormSuccess: function(dialog, xhr) {
    var data = this._getDataFromKeyForm();

    // replace the keyId from the one in the response, if it was empty, we'll have generated the x5t when certificate
    data.keyId = JSON.parse(xhr.responseText).keyId || '';

    var row = null;
    this.keyTable.query('tbody tr').each(function(r) {
      if (r.getDataSet().keyId === data.keyId) {
        row = r;
      }
    });

    if (row === null) {
      row = this.expandableKeyTable.addRow(data);
    }

    var dataSet = row.getDataSet();
    dataSet.keyId = data.keyId;
    dataSet.encodedKey = data.encodedKey;

    this._replaceKeyFieldValues(data);

    // Finally close the dialog
    this.keyDialog.close();
  },

  /**
   * Handles the tab selection and enables CodeMirror on the Data Definition tab.
   *
   * @param {Object} tab The &lt;li&gt; tab element that was selected.
   * @param {Object} tabContent The &lt;div&gt; that contains the tab contents.
   * @private
   */
  _handleTabSelect: function(tab, tabContent) {
    if (tabContent.getId() === 'domains') {
      this.domainEditor.render();
    }
  },

  _handleViewKeyClick: function(event, target) {
    var button = new Prime.Document.Element(target);
    Prime.Utils.stopEvent(event);

    var dialog = Prime.Document.queryById('key-view');
    var viewKeyId = Prime.Document.queryById('view-key-id');
    var viewEncodedKey = Prime.Document.queryById('view-encoded-key');

    var tr = button.queryUp('tr');
    viewKeyId.setHTML(tr.getDataAttribute('keyId') || '&ndash;');
    viewEncodedKey.setHTML(tr.getDataAttribute('encodedKey'));

    new Prime.Widgets.HTMLDialog(dialog)
        .initialize()
        .open();
  },

  /**
   * Need to move the updated data-XXX attributes into the row, otherwise the edits won't get passed to the action.
   */
  _replaceKeyFieldValues: function(data) {
    Prime.Document.queryById('identityProviders.keys_' + data.keyId).setValue(data.encodedKey);
  },

  /**
   * Need to move the updated data-XXX attributes into the row, otherwise the edits won't get passed to the action.
   */
  _replaceClaimFieldValues: function(data) {
    var input = Prime.Document.queryById('identityProviders.claimMap_' + data.incomingClaim);
    input.setValue(data.fusionAuthClaim);

    input.queryUp('td').getNextSibling().setHTML(data.fusionAuthClaim);
  },

  _toggleKeyIdField: function() {
    if (this.addDefaultCheckbox.isChecked()) {
      this.addKeyId.setAttribute('placeholder', '').setDisabled(true);
    } else {
      this.addKeyId.setAttribute('placeholder', this.addKeyId.getAttribute('data-placeholder'))
          .setDisabled(false)
    }
  }
};
