define('xwiki-ckeditor-inline', ['jquery', 'xwiki-ckeditor'], function($, ckeditorPromise) {
  var loadCSS = function(url) {
    var link = $('<link>').attr({
      type: 'text/css',
      rel: 'stylesheet',
      href: url
    }).appendTo('head');
  };

  var css = [
    // Styles for the editor UI (tool bar, dialogs, etc.).
    new XWiki.Document('EditSheet', 'CKEditor').getURL('ssx'),
    // Custom styles for the edited content.
    new XWiki.Document('ContentSheet', 'CKEditor').getURL('ssx'),
    "../../webjars/application-ckeditor-webjar/1.61/plugins/xwiki-resource/resourcePicker.min.css",
    "../../webjars/application-ckeditor-webjar/1.61/plugins/xwiki-macro/macroWizard.min.css",
    "../../webjars/xwiki-platform-tree-webjar/14.2.1/tree.min.css",
    "../../webjars/xwiki-platform-tree-webjar/14.2.1/finder.min.css"
  ];
  css.forEach(loadCSS);

  $(document).on('xwiki:actions:edit', function(event, config) {
    if (config && config.contentType === 'org.xwiki.rendering.syntax.SyntaxContent' && config.editMode === 'wysiwyg') {
      var container = $(event.target);
      ckeditorPromise.done(function(ckeditor) {
        createEditors(ckeditor, container, config);
      });
    }
  });

  var createEditors = function(ckeditor, container, config) {
    container.attr({
      'data-sourceDocumentReference': XWiki.Model.serialize(config.document.documentReference),
      'data-sourceDocumentSyntax': config.document.syntax,
      'data-officeImporterSupported': config.enableOfficeImport,
      'data-syntax': 'syntax' in config ? config['syntax'] : 'annotatedxhtml/1.0'
    }).each(function() {
      try {
        createEditor(ckeditor, this, config).done(config.deferred.resolve.bind(config.deferred, config.document));
      } catch (e) {
        console.log(e);
        new XWiki.widgets.Notification("Failed to initialize CKEditor.", 'error');
        config.deferred.reject();
      }
    });
  };

  var createEditor = function(ckeditor, element, config, instanceConfig) {
    var deferred = $.Deferred();
    var editor = ckeditor.inline(element, $.extend({
      // It doesn't make sense to resize the editor when editing in-line and it also creates problems with the way
      // we implemented the maximize feature for the in-line editor.
      resize_enabled: false
    }, instanceConfig));
    // Disable the source mode if the in-place editor doesn't support it, i.e. XWiki [12.3RC1, 12.4].
    if (!config.enableSourceMode) {
      editor.once('configLoaded', function(event) {
        if (typeof editor.config.removePlugins === 'string') {
          editor.config.removePlugins += ',xwiki-source,xwiki-sourcearea';
        }
      });
    }
    editor.once('instanceReady', function() {
      deferred.resolve(editor);
      // Make the content editable after the editor is ready and visible.
      // See CKEDITOR-390: The inline editor loads as read-only in Safari
      editor.setReadOnly(false);
    });
    editor.once('reload', function(event) {
      $(document).off(['xwiki:actions:view.contentEditor', 'xwiki:actions:beforeSave.contentEditor'].join(' '));
      event.data.promise = event.data.promise.then(createEditor.bind(null, ckeditor, element, config));
    });
    $(document).on('xwiki:actions:beforeSave.contentEditor', function(event) {
      config.document[editor.mode === 'source' ? 'content' : 'renderedContent'] = editor.getData();
      config.document.syntax = $(element).attr('data-sourceDocumentSyntax');
    });
    $(document).one('xwiki:actions:view.contentEditor', function(event, data) {
      $(document).off('xwiki:actions:beforeSave.contentEditor');
      // Blur the edited content to re-enable the "disabled in inputs" shortcut keys (e.g. the page edit shortcut).
      // We also do this because destroying the editor while the edited content has the focus can lead to an error.
      // See below.
      $(element).blur().prop('contenteditable', false).removeAttr('contenteditable');
      // We destroy the editor after the edited content has lost the focus completely because the editor has a
      // delayed event listener that tries to access the selection even after the editor has been destroyed.
      setTimeout(function() {
        // Don't update the edited element with the data from the editor because:
        // * the editor data might be wiki syntax if the current mode is Source
        // * the in-place editor updates the edited element anyway using the view HTML (without rendering markers)
        //   and we risk overwriting it.
        editor.destroy(/* noUpdate: */ true);
      }, 0);
    });
    return deferred.promise();
  };
});
