/**
 * @file
 * A Backbone View that provides an interactive toolbar (1 per in-place editor).
 */

(function ($, _, Backbone, Drupal) {
  Drupal.quickedit.FieldToolbarView = Backbone.View.extend(/** @lends Drupal.quickedit.FieldToolbarView# */{

    /**
     * The edited element, as indicated by EditorView.getEditedElement.
     *
     * @type {jQuery}
     */
    $editedElement: null,

    /**
     * A reference to the in-place editor.
     *
     * @type {Drupal.quickedit.EditorView}
     */
    editorView: null,

    /**
     * @type {string}
     */
    _id: null,

    /**
     * @constructs
     *
     * @augments Backbone.View
     *
     * @param {object} options
     *   Options object to construct the field toolbar.
     * @param {jQuery} options.$editedElement
     *   The element being edited.
     * @param {Drupal.quickedit.EditorView} options.editorView
     *   The EditorView the toolbar belongs to.
     */
    initialize(options) {
      this.$editedElement = options.$editedElement;
      this.editorView = options.editorView;

      /**
       * @type {jQuery}
       */
      this.$root = this.$el;

      // Generate a DOM-compatible ID for the form container DOM element.
      this._id = `quickedit-toolbar-for-${this.model.id.replace(/[\/\[\]]/g, '_')}`;

      this.listenTo(this.model, 'change:state', this.stateChange);
    },

    /**
     * @inheritdoc
     *
     * @return {Drupal.quickedit.FieldToolbarView}
     *   The current FieldToolbarView.
     */
    render() {
      // Render toolbar and set it as the view's element.
      this.setElement($(Drupal.theme('quickeditFieldToolbar', {
        id: this._id,
      })));

      // Attach to the field toolbar $root element in the entity toolbar.
      this.$el.prependTo(this.$root);

      return this;
    },

    /**
     * Determines the actions to take given a change of state.
     *
     * @param {Drupal.quickedit.FieldModel} model
     *   The quickedit FieldModel
     * @param {string} state
     *   The state of the associated field. One of
     *   {@link Drupal.quickedit.FieldModel.states}.
     */
    stateChange(model, state) {
      const from = model.previous('state');
      const to = state;
      switch (to) {
        case 'inactive':
          break;

        case 'candidate':
          // Remove the view's existing element if we went to the 'activating'
          // state or later, because it will be recreated. Not doing this would
          // result in memory leaks.
          if (from !== 'inactive' && from !== 'highlighted') {
            this.$el.remove();
            this.setElement();
          }
          break;

        case 'highlighted':
          break;

        case 'activating':
          this.render();

          if (this.editorView.getQuickEditUISettings().fullWidthToolbar) {
            this.$el.addClass('quickedit-toolbar-fullwidth');
          }

          if (this.editorView.getQuickEditUISettings().unifiedToolbar) {
            this.insertWYSIWYGToolGroups();
          }
          break;

        case 'active':
          break;

        case 'changed':
          break;

        case 'saving':
          break;

        case 'saved':
          break;

        case 'invalid':
          break;
      }
    },

    /**
     * Insert WYSIWYG markup into the associated toolbar.
     */
    insertWYSIWYGToolGroups() {
      this.$el
        .append(Drupal.theme('quickeditToolgroup', {
          id: this.getFloatedWysiwygToolgroupId(),
          classes: ['wysiwyg-floated', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'],
          buttons: [],
        }))
        .append(Drupal.theme('quickeditToolgroup', {
          id: this.getMainWysiwygToolgroupId(),
          classes: ['wysiwyg-main', 'quickedit-animate-slow', 'quickedit-animate-invisible', 'quickedit-animate-delay-veryfast'],
          buttons: [],
        }));

      // Animate the toolgroups into visibility.
      this.show('wysiwyg-floated');
      this.show('wysiwyg-main');
    },

    /**
     * Retrieves the ID for this toolbar's container.
     *
     * Only used to make sane hovering behavior possible.
     *
     * @return {string}
     *   A string that can be used as the ID for this toolbar's container.
     */
    getId() {
      return `quickedit-toolbar-for-${this._id}`;
    },

    /**
     * Retrieves the ID for this toolbar's floating WYSIWYG toolgroup.
     *
     * Used to provide an abstraction for any WYSIWYG editor to plug in.
     *
     * @return {string}
     *   A string that can be used as the ID.
     */
    getFloatedWysiwygToolgroupId() {
      return `quickedit-wysiwyg-floated-toolgroup-for-${this._id}`;
    },

    /**
     * Retrieves the ID for this toolbar's main WYSIWYG toolgroup.
     *
     * Used to provide an abstraction for any WYSIWYG editor to plug in.
     *
     * @return {string}
     *   A string that can be used as the ID.
     */
    getMainWysiwygToolgroupId() {
      return `quickedit-wysiwyg-main-toolgroup-for-${this._id}`;
    },

    /**
     * Finds a toolgroup.
     *
     * @param {string} toolgroup
     *   A toolgroup name.
     *
     * @return {jQuery}
     *   The toolgroup element.
     */
    _find(toolgroup) {
      return this.$el.find(`.quickedit-toolgroup.${toolgroup}`);
    },

    /**
     * Shows a toolgroup.
     *
     * @param {string} toolgroup
     *   A toolgroup name.
     */
    show(toolgroup) {
      const $group = this._find(toolgroup);
      // Attach a transitionEnd event handler to the toolbar group so that
      // update events can be triggered after the animations have ended.
      $group.on(Drupal.quickedit.util.constants.transitionEnd, (event) => {
        $group.off(Drupal.quickedit.util.constants.transitionEnd);
      });
      // The call to remove the class and start the animation must be started in
      // the next animation frame or the event handler attached above won't be
      // triggered.
      window.setTimeout(() => {
        $group.removeClass('quickedit-animate-invisible');
      }, 0);
    },

  });
}(jQuery, _, Backbone, Drupal));
