var XWiki = (function (XWiki) {

XWiki.EntryNamePopup = Class.create(XWiki.widgets.ModalPopup, {
  initialize : function($super, trigger) {
    trigger.observe('click', this.showDialog.bindAsEventListener(this));
    this.urlTemplate = trigger.up().next('input[type=hidden]').value;

    this.input = new Element('input', {type: 'text'});
    this.addButton = new Element('input', {
      type: 'image',
      src: '$xwiki.getSkinFile('icons/silk/add.png')',
      alt: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageAddEntryLabel'))'
    });

    var container = new Element('div', {id: 'entryNamePopup'});
    container.insert(this.input);
    container.insert(this.addButton);

    $super(container, {
      show: {method: this.showDialog, keys: []},
      add: {method: this._onAdd, keys: ['Enter']}
    }, {
      title: '$escapetool.javascript($services.localization.render('platform.appwithinminutes.appHomePageEntryNameLabel'))',
      verticalPosition: 'top'
    });
  },
  createDialog : function($super, event) {
    this.addButton.observe('click', this._onAdd.bind(this));
    $super(event);
  },
  showDialog : function($super, event) {
    $super(event);
    this.input.clear().focus();
  },
  _onAdd : function() {
    if (this.input.value != '') {
      // We use the global flag because we need to replace both the page name and its title.
      window.self.location = this.urlTemplate.replace(/__entryName__/g, encodeURIComponent(this.input.value));
    } else {
      this.input.focus();
    }
  }
});

function init() {
  var actionBox = $('actionBox');
  if(actionBox) {
    new XWiki.EntryNamePopup(actionBox.down('.add'));
    return true;
  }
  return false;
}
(XWiki.domIsLoaded && init()) || document.observe('xwiki:dom:loaded', init);

return XWiki;
}(XWiki || {}));

/**
 * Rename Application
 */
require(['jquery', 'bootstrap'], function($) {
  #set ($currentDocReference = $xwiki.getDocument($request.currentApp).getDocumentReference())
  // if we cannot find any extension related to this page app, it's not part of an extension.
  var isNotAnExtension = $services.extension.xar.getInstalledExtensions($currentDocReference).isEmpty();

  // double negation! if it's an extension, we stop there: we don't want to add custom AWM rename capabilities
  if (!isNotAnExtension) {
        return;
  }
  // Hijack the rename page action.
  var renameAppModal = $('#renameAppModal');
  $('#tmActionRename').click(function(event) {
    event.preventDefault();
    renameAppModal.modal();
  });

  // Form validation.
  var appNameInput = $('#renameAppTitle');
  var appParentInput = $('#renameAppParentReference');
  var submitButton = renameAppModal.find('.btn-primary[type="submit"]');

  var appNameEmptyError = renameAppModal.find('.appNameEmptyError');
  var pageExistsError = renameAppModal.find('.pageExistsError');
  var locationForbiddenError = renameAppModal.find('.locationForbiddenError');
  appNameEmptyError.add(pageExistsError).add(locationForbiddenError).hide().insertAfter(appNameInput);

  var getNewAppReference = function(local) {
    var appParentReference = local ? null : new XWiki.WikiReference(XWiki.currentWiki);
    if (appParentInput.val() !== '') {
      appParentReference = XWiki.Model.resolve(appParentInput.val(), XWiki.EntityType.SPACE, appParentReference);
    }
    return new XWiki.EntityReference(appNameInput.val(), XWiki.EntityType.SPACE, appParentReference);
  };

  var getNewAppHomePage = function() {
    var newAppReference = getNewAppReference();
    var newAppHomePageReference = new XWiki.EntityReference('WebHome', XWiki.EntityType.DOCUMENT, newAppReference);
    return new XWiki.Document(newAppHomePageReference);
  };

  var startValidation = function() {
    if (appNameInput.val() === '') {
      endValidation(appNameEmptyError);
    } else {
      var newAppHomePage = getNewAppHomePage();
      if (newAppHomePage.documentReference.equals(XWiki.currentDocument.documentReference)) {
        endValidation(pageExistsError);
      } else {
        $.ajax({
          type: 'HEAD',
          url: newAppHomePage.getURL()
        }).done(function() {
          endValidation(pageExistsError);
        }).fail(function(response) {
          if (response.status === 404) {
            $.ajax({
              type: 'HEAD',
              url: newAppHomePage.getURL('edit')
            }).done(function() {
              endValidation();
            }).fail(function() {
              endValidation(locationForbiddenError);
            });
          } else if (response.status === 403) {
            endValidation(locationForbiddenError);
          } else {
            endValidation();
          }
        });
      }
    }
  };

  var endValidation = function(error) {
    if (error) {
      error.show();
    }
    appNameInput.removeClass('loading');
    submitButton.prop('disabled', !!error);
  };

  var validationTimeout;
  var scheduleValidation = function() {
    clearTimeout(validationTimeout);
    renameAppModal.find('.xErrorMsg').hide();
    appNameInput.addClass('loading');
    submitButton.prop('disabled', true);
    validationTimeout = setTimeout(startValidation, 500);
  };

  appNameInput.add(appParentInput).on('input', scheduleValidation);

  var locationPickerModal = renameAppModal.find('.location-picker .modal');
  renameAppModal.on('shown.bs.modal', function(event) {
    // Nested modals are not supported so we have to move the location picker modal outside, but we shouldn't do this
    // before the location picker has been initialized. That's why we wait for the rename application modal to be shown
    // first.
    renameAppModal.after(locationPickerModal);
    appNameInput.focus();
  });

  // Hide the rename application modal when the location picker modal is shown.
  locationPickerModal.removeClass('fade').on('show.bs.modal', function(event) {
    renameAppModal.modal('hide');
  // Show the rename application modal when the location picker modal is hidden.
  }).on('hidden.bs.modal', function(event) {
    renameAppModal.modal('show');
  });

  renameAppModal.find('form').submit(function(event) {
    event.preventDefault();
    renameApp(getRenameData($(this)));
  });

  var getRenameData = function(form) {
    var data = getFormData(form);
    data.newAppReference = XWiki.Model.serialize(getNewAppReference(true));
    delete data.newAppName;
    delete data.newAppParentReference;
    data.outputSyntax = 'plain';
    return data;
  };

  var getFormData = function(form) {
    var data = {};
    form.serializeArray().forEach(function(parameter) {
      // Keep the first value;
      if (!data.hasOwnProperty(parameter.name)) {
        data[parameter.name] = parameter.value;
      }
    });
    return data;
  };

  var renameApp = function(data) {
    // Disable the form to prevent it from being submitted twice.
    renameAppModal.find(':input').prop('disabled', true);
    var notification = new XWiki.widgets.Notification(
      $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.inProgress')),
      'inprogress'
    );
    var renameAppURL = new XWiki.Document('RenameApplication', 'AppWithinMinutes').getURL('get');
    $.post(renameAppURL, data).then(updateAppHomePage).done(function() {
      renameAppModal.modal('hide');
      notification.replace(new XWiki.widgets.Notification(
        $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.done')),
        'done'
      ));
      // Delay a bit the redirect so that the user notices the success message.
      setTimeout(function() {
        window.location.href = getNewAppHomePage().getURL();
      }, 0);
    }).fail(function() {
      notification.replace(new XWiki.widgets.Notification(
        $jsontool.serialize($services.localization.render('appWithinMinutes.renameApp.failed')),
        'error'
      ));
    }).always(function() {
      // Re-enable the form.
      renameAppModal.find(':input').prop('disabled', false);
    });
  };

  var updateAppHomePage = function() {
    var deferred = $.Deferred();
    var newAppHomePageEditURL = getNewAppHomePage().getURL('edit');
    $('<div/>').load(newAppHomePageEditURL + ' #inline', function() {
      var formData = $(this).children('form#inline').serializeArray();
      if (formData.length > 0) {
        formData.push({name: 'xaction_save', value: true});
        $.post(newAppHomePageEditURL, formData).done(function() {
          deferred.resolve();
        }).fail(function() {
          deferred.reject();
        });
      } else {
        deferred.reject();
      }
    });
    return deferred.promise();
  }
});
