/**
* DO NOT EDIT THIS FILE.
* See the following change record for more information,
* https://www.drupal.org/node/2815083
* @preserve
**/

(function (jQuery, Drupal, CKEDITOR) {
  function getFocusedWidget(editor) {
    const widget = editor.widgets.focused;

    if (widget && widget.name === 'drupalmedia') {
      return widget;
    }

    return null;
  }

  function linkCommandIntegrator(editor) {
    if (!editor.plugins.drupallink) {
      return;
    }

    CKEDITOR.plugins.drupallink.registerLinkableWidget('drupalmedia');
    editor.getCommand('drupalunlink').on('exec', function (evt) {
      const widget = getFocusedWidget(editor);

      if (!widget) {
        return;
      }

      widget.setData('link', null);
      this.refresh(editor, editor.elementPath());
      evt.cancel();
    });
    editor.getCommand('drupalunlink').on('refresh', function (evt) {
      const widget = getFocusedWidget(editor);

      if (!widget) {
        return;
      }

      this.setState(widget.data.link ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED);
      evt.cancel();
    });

    if (editor.contextMenu) {
      editor.contextMenu.addListener(() => {
        const widget = getFocusedWidget(editor);

        if (!widget) {
          return;
        }

        if (widget.data.link) {
          return {
            link: CKEDITOR.TRISTATE_OFF,
            unlink: CKEDITOR.TRISTATE_OFF
          };
        }

        return {};
      });
    }
  }

  CKEDITOR.plugins.add('drupalmedia', {
    requires: 'widget',

    beforeInit(editor) {
      const {
        dtd
      } = CKEDITOR;
      dtd['drupal-media'] = {
        '#': 1
      };
      Object.keys(dtd).forEach(tagName => {
        if (dtd[tagName].div) {
          dtd[tagName]['drupal-media'] = 1;
        }
      });
      dtd.a['drupal-media'] = 1;
      editor.widgets.add('drupalmedia', {
        allowedContent: {
          'drupal-media': {
            attributes: {
              '!data-entity-type': true,
              '!data-entity-uuid': true,
              'data-align': true,
              'data-caption': true,
              alt: true,
              title: true
            },
            classes: {}
          }
        },
        requiredContent: new CKEDITOR.style({
          element: 'drupal-media',
          attributes: {
            'data-entity-type': '',
            'data-entity-uuid': ''
          }
        }),
        pathName: Drupal.t('Embedded media'),
        editables: {
          caption: {
            selector: 'figcaption',
            allowedContent: 'a[!href]; em strong cite code br',
            pathName: Drupal.t('Caption')
          }
        },

        getLabel() {
          if (this.data.label) {
            return this.data.label;
          }

          return Drupal.t('Embedded media');
        },

        upcast(element, data) {
          const {
            attributes
          } = element;

          if (element.name !== 'drupal-media' || attributes['data-entity-type'] !== 'media' || attributes['data-entity-uuid'] === undefined) {
            return;
          }

          data.attributes = CKEDITOR.tools.copy(attributes);
          data.hasCaption = data.attributes.hasOwnProperty('data-caption');

          if (data.hasCaption && data.attributes['data-caption'] === '') {
            data.attributes['data-caption'] = ' ';
          }

          data.label = null;
          data.link = null;

          if (element.parent.name === 'a') {
            data.link = CKEDITOR.tools.copy(element.parent.attributes);
            Object.keys(element.parent.attributes).forEach(attrName => {
              if (attrName.indexOf('data-cke-') !== -1) {
                delete data.link[attrName];
              }
            });
          }

          const hostEntityLangcode = document.getElementById(editor.name).getAttribute('data-media-embed-host-entity-langcode');

          if (hostEntityLangcode) {
            data.hostEntityLangcode = hostEntityLangcode;
          }

          return element;
        },

        destroy() {
          this._tearDownDynamicEditables();
        },

        data(event) {
          if (this.oldData) {
            if (!this.data.hasCaption && this.oldData.hasCaption) {
              delete this.data.attributes['data-caption'];
            } else if (this.data.hasCaption && !this.data.attributes['data-caption']) {
              this.data.attributes['data-caption'] = ' ';
            }
          }

          if (this._previewNeedsServerSideUpdate()) {
            editor.fire('lockSnapshot');

            this._tearDownDynamicEditables();

            this._loadPreview(widget => {
              widget._setUpDynamicEditables();

              widget._setUpEditButton();

              editor.fire('unlockSnapshot');
            });
          }

          if (this.oldData) {
            Object.keys(this.oldData.attributes).forEach(attrName => {
              this.element.removeAttribute(attrName);
            });
          }

          this.element.setAttributes(this.data.attributes);
          this.oldData = CKEDITOR.tools.clone(this.data);
        },

        downcast() {
          const downcastElement = new CKEDITOR.htmlParser.element('drupal-media', this.data.attributes);

          if (this.data.link) {
            const link = new CKEDITOR.htmlParser.element('a', this.data.link);
            link.add(downcastElement);
            return link;
          }

          return downcastElement;
        },

        _setUpDynamicEditables() {
          if (this.initEditable('caption', this.definition.editables.caption)) {
            const captionEditable = this.editables.caption;
            captionEditable.setAttribute('data-placeholder', Drupal.t('Enter caption here'));
            this.captionObserver = new MutationObserver(() => {
              const mediaAttributes = CKEDITOR.tools.clone(this.data.attributes);
              mediaAttributes['data-caption'] = captionEditable.getData();
              this.setData('attributes', mediaAttributes);
            });
            this.captionObserver.observe(captionEditable.$, {
              characterData: true,
              attributes: true,
              childList: true,
              subtree: true
            });

            if (captionEditable.$.childNodes.length === 1 && captionEditable.$.childNodes.item(0).nodeName === 'BR') {
              captionEditable.$.removeChild(captionEditable.$.childNodes.item(0));
            }
          }
        },

        _setUpEditButton() {
          if (this.element.findOne('.media-embed-error')) {
            return;
          }

          const isElementNode = function (n) {
            return n.type === CKEDITOR.NODE_ELEMENT;
          };

          const embeddedMediaContainer = this.data.hasCaption ? this.element.findOne('figure') : this.element;
          let embeddedMedia = embeddedMediaContainer.getFirst(isElementNode);

          if (this.data.link) {
            embeddedMedia = embeddedMedia.getFirst(isElementNode);
          }

          embeddedMedia.setStyle('position', 'relative');
          const editButton = CKEDITOR.dom.element.createFromHtml(Drupal.theme('mediaEmbedEditButton'));
          embeddedMedia.getFirst().insertBeforeMe(editButton);
          const widget = this;
          this.element.findOne('.media-library-item__edit').on('click', event => {
            const saveCallback = function (values) {
              event.cancel();
              editor.fire('saveSnapshot');

              if (values.hasOwnProperty('attributes')) {
                CKEDITOR.tools.extend(values.attributes, widget.data.attributes);
                Object.keys(values.attributes).forEach(prop => {
                  if (values.attributes[prop] === false || prop === 'data-align' && values.attributes[prop] === 'none') {
                    delete values.attributes[prop];
                  }
                });
              }

              widget.setData({
                attributes: values.attributes,
                hasCaption: !!values.hasCaption
              });
              editor.fire('saveSnapshot');
            };

            Drupal.ckeditor.openDialog(editor, Drupal.url(`editor/dialog/media/${editor.config.drupal.format}`), widget.data, saveCallback, {});
          });
          this.element.findOne('.media-library-item__edit').on('keydown', event => {
            const returnKey = 13;
            const spaceBar = 32;

            if (typeof event.data !== 'undefined') {
              const keypress = event.data.getKey();

              if (keypress === returnKey || keypress === spaceBar) {
                event.sender.$.click();
              }

              event.data.$.stopPropagation();
              event.data.$.stopImmediatePropagation();
            }
          });
        },

        _tearDownDynamicEditables() {
          if (this.captionObserver) {
            this.captionObserver.disconnect();
          }
        },

        _previewNeedsServerSideUpdate() {
          if (!this.ready) {
            return true;
          }

          return this._hashData(this.oldData) !== this._hashData(this.data);
        },

        _hashData(data) {
          const dataToHash = CKEDITOR.tools.clone(data);
          delete dataToHash.attributes['data-caption'];
          delete dataToHash.label;

          if (dataToHash.link) {
            delete dataToHash.link.href;
          }

          return JSON.stringify(dataToHash);
        },

        _loadPreview(callback) {
          jQuery.get({
            url: Drupal.url(`media/${editor.config.drupal.format}/preview`),
            data: {
              text: this.downcast().getOuterHtml(),
              uuid: this.data.attributes['data-entity-uuid']
            },
            dataType: 'html',
            headers: {
              'X-Drupal-MediaPreview-CSRF-Token': editor.config.drupalMedia_previewCsrfToken
            },
            success: (previewHtml, textStatus, jqXhr) => {
              this.element.setHtml(previewHtml);
              this.setData('label', jqXhr.getResponseHeader('Drupal-Media-Label'));
              callback(this);
            },
            error: () => {
              this.element.setHtml(Drupal.theme('mediaEmbedPreviewError'));
            }
          });
        }

      });
    },

    afterInit(editor) {
      linkCommandIntegrator(editor);
    }

  });
})(jQuery, Drupal, CKEDITOR);