define('licensor', ['jquery', 'xwiki-meta'], function($, xwikiMeta) {
  return {
    addLicense: function(data) {
      return $.post(
        new XWiki.Document('AddLicense', 'Licenses.Code').getURL('get', 'outputSyntax=plain'),
        data
      ).then(null, function(result) {
        return result.responseJSON ? result.responseJSON : {
          status: 'error',
          notification: "Unexpected error: Received non-JSON content. Please contact sales@xwiki.com."
        };
      }).done(function() {
        $(document).trigger('xwiki:license:added');
      });
    },
    updateLicenses: function() {
      return $.post(
        new XWiki.Document('UpdateLicenses', 'Licenses.Code').getURL('get'),
        {
          outputSyntax: 'plain',
          form_token: xwikiMeta.form_token,
          confirm: true
        }
      ).then(null, function(result) {
        return result.responseJSON ? result.responseJSON : {
          status: 'error',
          notification: "Unexpected error: Received non-JSON content. Please contact sales@xwiki.com."
        };
      }).done(function(result) {
        if (result.updateCount && result.updateCount > 0) {
          $(document).trigger('xwiki:license:updated');
        }
      });
    },
    getTrialLicense: function(data) {
      return $.post(
        new XWiki.Document('GetTrialLicenseService', 'Licenses.Code').getURL('get', 'outputSyntax=plain'),
        data
      ).then(null, function(result) {
        return result.responseJSON ? result.responseJSON : {
          status: 'error',
          data: "Unexpected error: Received non-JSON content. Please contact sales@xwiki.com."
        };
      });
    },
    updateOwnerDetails: function(data) {
      return $.post(
        new XWiki.Document('UpdateOwnerDetails', 'Licenses.Code').getURL('get', 'outputSyntax=plain'),
        data
      );
    },
    modifyAutoUpgradesAllowList: function(data) {
      return $.post(
        new XWiki.Document('UpdateAutomaticUpgradesAllowList', 'Licenses.Code').getURL('get', 'outputSyntax=plain'),
        data
      );
    }
  };
});

require(['jquery', 'licensor', 'xwiki-meta', 'xwiki-events-bridge', 'bootstrap'], function ($, licensor, xwikiMeta) {
  //
  // Owner Details Form
  //

  var validateOwnerDetails = function(ownerDetailsForm) {
    // Make sure required details are not missing.
    var valid = true;
    var focus = true;
    ownerDetailsForm.find('input:visible').each(function() {
      $(this).removeClass('required');
      var inputValue = $(this).val().trim();
      // Check for a minimum number of chars filled in by the user.
      if (inputValue.length < 2) {
        // Focus on first element that needs to be filled with data.
        if (focus) {
          $(this).focus();
          focus = false;
        }
        valid = false;
        $(this).addClass('required');
        $(this).attr('placeholder', "This field is required!");
      }
    });
    return valid;
  };

  //
  // Add License Form
  //

  var addLicense = function(data) {
    var addLicenseForm = $('form#addLicense');
    // Disable the form.
    addLicenseForm.find(':input').prop('disabled', true);
    // Show a notification message.
    var progressNotification = new XWiki.widgets.Notification("Adding license...", 'inprogress');
    licensor.addLicense(data).always(function(result) {
      // Update the notification message.
      progressNotification.replace(new XWiki.widgets.Notification(result.notification, result.status));
      // Re-enable the form.
      addLicenseForm.find(':input').prop('disabled', false);
    }).done(function() {
      // Clear the license text area.
      $('textarea#license').val('');
    });
  };

  $("form#addLicense").submit(function(event) {
    event.preventDefault();
    addLicense($(this).serialize());
  });

  //
  // Licensed Extensions Live Table
  //

  var computeHasTrialKey = function(instanceId, featureId) {
    return instanceId + '_' + featureId;
  };

  // Remove "Extend Trial" buttons from livetable, if the trial licenses limits were reached.
  var updateLivetableButtons = function() {
    var instanceId = $('#instanceId').val();
    $('.licenseActions .licenseButton-extendTrial').each(function() {
      // Compute the key to check in the localStorage.
      var buttonData = JSON.parse($(this).attr('data-button'));
      var featureId = buttonData.featureId;
      var hasTrialsKey = computeHasTrialKey(instanceId, featureId);
      // The value is stored as a string in the local storage.
      if (localStorage.getItem(hasTrialsKey) === 'false') {
        // Remove the "Extend Trial" button.
        $(this).remove();
      }
    });
  };

  // An extensionId could have multiple rows in the livetable if is installed on multiple subwikis, but the allowlist
  // is applied to all namespaces.
  var updateExtensionOfOtherWikis = function(extensionId, isAutoUpgrade) {
    var similarExtensions = $("input[name='extensionId'][value='" + extensionId + "']");
    similarExtensions.each(function() {
      var autoUpgradeButton = $(this).siblings('.licenseButton-autoUpgrade');
      autoUpgradeButton.find('.action-icon').toggleClass('isAutoUpgrade', isAutoUpgrade);
      var translationKey = isAutoUpgrade ? 'data-prevent-label' : 'data-allow-label';
      autoUpgradeButton.prop('title', autoUpgradeButton.attr(translationKey));
    });
  };

  // xwiki:livetable:displayComplete might be triggered before the code from this jsx is executed. In this case, the
  // livetable is also loaded before, because it is using Prototype.js which is loading before the page loads.
  // Make sure that the livetable is loaded by checking for a row with some data.
  if ($('#licenseManager-display td.type').size() > 0) {
    updateLivetableButtons();
  }
  $(document).on('xwiki:livetable:displayComplete', updateLivetableButtons);

  // Reload the live table of licensed extensions when licenses are added or updated.
  var reloadTimeoutId;
  $(document).on('xwiki:license:added xwiki:license:updated', function() {
    clearTimeout(reloadTimeoutId);
    reloadTimeoutId = setTimeout(function() {
      if ($.type(window.livetable_licenseManager) !== 'undefined') {
        // Reload the livetable.
        livetable_licenseManager.refresh();
      }
    }, 0);
  });

  var getValue = function(arrayOfNameValuePairs, name) {
    return arrayOfNameValuePairs.filter(function(pair) {
      return pair.name === name
    })[0].value;
  };

  var getTrialLicense = function(data, trialButton) {
    trialButton.prop('disabled', true);
    var progressNotification = new XWiki.widgets.Notification(
      "Getting trial license...", 'inprogress');
    licensor.getTrialLicense(data).always(function() {
      trialButton.prop('disabled', false);
    }).done(function(result) {
      // Cache the "hasTrials" value in local storage.
      var hasTrialsKey = computeHasTrialKey(getValue(data, 'instanceId'), getValue(data, 'featureId'));
      var hasTrialValue = result.hasTrials;
      localStorage.setItem(hasTrialsKey, hasTrialValue);
      // Hide the "Extend Trial" button if "hasTrials" is false.
      if (hasTrialValue === false) {
        trialButton.hide();
      }
      // We hide the notification message because addLicense will show its own notification message.
      progressNotification.hide();
      addLicense({
        license: result.data,
        form_token: xwikiMeta.form_token
      });
    }).fail(function(result) {
      progressNotification.replace(new XWiki.widgets.Notification(result.data, result.status));
    });
  };

  // Manages the license buttons from the licenses livetable. If a trial is requested, it is automatically generated
  // and installed, else the user is redirected to a page to buy a license.
  $('#licenseManager').on('click', '.licenseButton', function(e) {
    e.preventDefault();
    var ownerDetailsForm = $('#ownerDetails');
    if (!validateOwnerDetails(ownerDetailsForm)) {
      return;
    }
    // Update the owner details.
    var ownerDetails = ownerDetailsForm.serializeArray();
    licensor.updateOwnerDetails(ownerDetails);
    // Get the data from the license button.
    var buttonData = JSON.parse($(this).attr('data-button'));
    if (buttonData.licenseType === 'TRIAL') {
      ownerDetails.push.apply(ownerDetails, $.map(buttonData, function(value, name) {
        return {name: name, value: value};
      }));
      getTrialLicense(ownerDetails, $(this));
    } else if (buttonData.licenseType === 'PAID') {
      var extraFields = $($.map(buttonData, function(value, name) {
        return $("<input type='hidden'/>").attr({name: name, value: value})[0];
      }));
      ownerDetailsForm.append(extraFields).submit();
      extraFields.remove();
    };
  });

  // Show a popover on the "Check for Updates" button to let the user know what to do after he pays for the license.
  $('#updateLicenses').each(function() {
    // Initialize the popover with a different title.
    var originalTitle = $(this).attr('title');
    // We trigger the popover manually after the user clicks on the Buy/Extend license button.
    $(this).attr('title', $(this).attr('data-title')).popover({trigger: 'manual'}).attr('title', originalTitle);
  });

  $('#ownerDetails').submit(function () {
    var updateLicensesButton = $('#updateLicenses');
    updateLicensesButton.one('click', function() {
      // Hide the popover on the first click.
      $(this).popover('hide');
    });
    updateLicensesButton[0].scrollIntoView();
    updateLicensesButton.focus().popover('show');
  });

  $('#updateLicenses').click(function() {
    var updateButton = $(this);
    updateButton.prop('disabled', true);
    // Show a notification message.
    var progressNotification = new XWiki.widgets.Notification(
      "Checking...", 'inprogress');
    licensor.updateLicenses().always(function(result) {
      updateButton.prop('disabled', false);
      // Update the notification message.
      progressNotification.replace(new XWiki.widgets.Notification(result.notification, result.status));
    });
  });

  $(document).on('click', '.licenseButton-autoUpgrade', function(e) {
    e.preventDefault();
    var autoUpgradeButton = $(this);
    var autoUpgradeForm = autoUpgradeButton.closest('form').serializeArray();
    licensor.modifyAutoUpgradesAllowList(autoUpgradeForm).success(function(data) {
      autoUpgradeButton.find('.action-icon').toggleClass('isAutoUpgrade', data.isAutoUpgrade);
      if(data.isAutoUpgrade) {
        autoUpgradeButton.prop('title', autoUpgradeButton.attr('data-prevent-label'));
        new XWiki.widgets.Notification(
          "Added to the list of auto-upgraded extensions", 'done');
      } else {
        autoUpgradeButton.prop('title', autoUpgradeButton.attr('data-allow-label'));
        new XWiki.widgets.Notification(
          "Removed from the list of auto-upgraded extensions", 'done');
      }
      updateExtensionOfOtherWikis(data.extensionId, data.isAutoUpgrade);
    });
  });

  // Set the documentation links to open in new tab.
  $('#licenseManager-display td.name a').each(function() {
    $(this).attr('target', '_blank')
  });
});
