
/**
 * Pagedesigner Media Manager
 *
 * Provides general methods for connecting Drupal media assets with the Grapes asset manager
 */
class PagedesignerMediaManager {

  /**
   * Construct a new Pagedesigner Media Manager.
   * Also, initializes the default media trait.
   *
   * @param {Object} editor
   * @param {Object} jQuery
   * @param {Object} settings
   */
  constructor(editor, jQuery, settings) {
    this.editor = editor;
    this.jQuery = jQuery;
    this.uploadType = 'file';

    if (typeof drupalSettings.pagedesigner.media == 'undefined') {
      drupalSettings.pagedesigner.media = {};
    }

    // Create generic media trait base definition
    this.mediaTrait =
      jQuery.extend(
        {},
        this.editor.TraitManager.defaultTrait,
        {
          afterInit: function () {
            jQuery(this.inputEl).on(
              'click',
              (function (trait) {
                return function (e) {
                  editor.PDMediaManager.loadForm(trait);
                }
              }(this))
            );
          },
          getInputEl: function () {
            if (!this.inputEl) {
              var button = jQuery('<button type="button" style="width:100%"></button>');
              button.text(Drupal.t('Choose') + ' ' + Drupal.t(this.model.get('type')));
              this.inputEl = button.get(0);
            }
            return this.inputEl;
          },
          getRenderValue: function () {
            if (this.model.get('value')) {
              return this.model.get('value').src;
            }
            return '';
          },
          setInputValue: function (value) {
            this.model.set('value', value);
          },
          setValueFromAssetManager: function (value) {
            this.model.set('value', value);
          },
          isMultiSelect: false
        }
      );
  }

  /**
   * Create a new trait with the given type/id based on the default media trait.
   *
   * @see https://grapesjs.com/docs/modules/Traits.html#define-new-trait-type
   * @param {String} type The type/id of the new trait.
   * @returns {Object} A trait with the given type/id.
   */
  addTrait(type, uploadType = 'file', traitExtension = null) {
    var trait = this.jQuery.extend({}, this.mediaTrait);
    if (traitExtension) {
      this.jQuery.extend(trait, traitExtension);
    }
    trait.uploadType = uploadType;
    this.editor.TraitManager.addType(type, trait);

    if (typeof drupalSettings.pagedesigner.media[type] == 'undefined') {
      drupalSettings.pagedesigner.media[type] = { translatable: false };
    }
    return this.editor.TraitManager.getType(type);
  }

  /**
   * Load and process the form based on the given trait.
   * Enables searching, paging and filtering according to trait type.
   *
   * @param {Object} trait The current trait.
   */
  loadForm(trait, type) {
    this.editor.AssetManager.add([]);
    this.editor.AssetManager.render();
    editor.runCommand('open-assets', {
      target: trait
    });

    if (!type) {
      type = trait.model.get('type');
    }
    if (trait.uploadType == 'text') {
      if (this.jQuery('#gjs-am-uploadText').length == 0) {
        this.jQuery('<div id="gjs-am-uploadText" class="gjs-am-uploadText-wrapper"></div>').insertAfter('#gjs-am-uploadFile');
        this.jQuery('#gjs-am-uploadText').append('<textarea class="upload-text" id="gjs-am-uploadText-value" placeholder="' + Drupal.t('Paste media links here, one per line.') + '"></textarea>');

        var uploadButton = this.jQuery('<button class="button button--primary btn-primary js-form-submit form-submit">' + Drupal.t('Upload links') + '</button>');
        uploadButton.on('click', function () {
          editor.AssetManager.getType(trait.model.get('type')).upload(jQuery('#gjs-am-uploadText-value').val());
          jQuery('#gjs-am-uploadText-value').val('');
        });


        this.jQuery('#gjs-am-uploadText').append(uploadButton);

      }
      this.jQuery('#gjs-am-title').hide();
      this.jQuery('#gjs-am-uploadFile').hide();
      this.jQuery('#gjs-am-uploadText').show();
    } else {
      this.jQuery('#gjs-am-title').show();
      this.jQuery('#gjs-am-uploadFile').show();
      this.jQuery('#gjs-am-uploadText').hide();
    }
    if (this.jQuery('.gjs-am-assets-header .gjs-am-add-asset').length == 0) {
      this.jQuery('.gjs-am-assets-header').empty().append('<div class="gjs-am-add-asset"></div>');
    }
    Drupal.ajax
      (
        {
          url: '/pagedesigner/form/asset/search/' + type
        }
      )
      .execute()
      .then(
        (function (self, type) {
          return function (data) {
            var id = null;
            if (trait && trait.model) {
              id = trait.model.get('value').id
            }
            setTimeout(() => self.processForm(type, id), 500);
          }
        })(this, type)
      );
  }

  /**
   * Process a loaded form to show only the given type and enable paging.
   *
   * @param {String} type The asset type to show.
   */
  processForm(type, mid) {
    var form = this.jQuery('.gjs-am-assets-header form');
    var showPrev = this.jQuery('<button class="pd-media-prev-button">&lt;&lt;</button>');
    var showNext = this.jQuery('<button class="pd-media-next-button">&gt;&gt;</button>');
    var AssetManager = this.editor.AssetManager;

    var pager = this.jQuery('<input type="hidden" name="page" value="0"></input>');
    form.append(pager);
    form.find('.form-row').find('input, select').change(function () {
      pager.val(0);
    });

    // Hide ID field.
    form.find('.form-item-mid').hide();

    form.on('submit', function (e) {
      e.preventDefault();
      var data = form.serialize();
      var url = Drupal.restconsumer.addFormat(form.attr('action')) + '&' + data;
      Drupal.restconsumer.get(url, true).done(function (response) {

        // Remove all existing assets.
        var assets = AssetManager.getAll();
        for (var x in assets) {
          AssetManager.getAll().remove(assets[x]);
        }

        if (mid != null) {
          // Remove selected element if in response.
          for (var x in response) {
            if (response[x].id == mid) {
              response.splice(x, 1);
            }
          }
        }

        // Add and filter the new assets.
        AssetManager.add(response);
        AssetManager.render(AssetManager.getAll().filter(
          function (asset) {
            if (type == '*') {
              return true;
            }
            return asset.get('type') == type
          }
        ));

        if (mid != null) {
          var single_url = Drupal.restconsumer.addFormat(form.attr('action')) + '&mid=' + mid;
          // Get the selected item and add it at the top.
          Drupal.restconsumer.get(single_url, true).done(function (response) {
            AssetManager.add(response);
          });
        }

      });
    });

    if (this.jQuery('.gjs-am-assets-cont').find('.pagination-holder').length == 0) {
      this.jQuery('.gjs-am-assets-cont').append('<div class="pagination-holder"></div>');
    } else {
      this.jQuery('.gjs-am-assets-cont').find('.pagination-holder').html('');
    }

    this.jQuery('.gjs-am-assets-cont').find('.pagination-holder').append(showPrev);
    showPrev.on('click', function () {
      if (pager.val() > 0) {
        pager.val(parseInt(pager.val()) - 1);
        form.find('.form-actions .form-submit').click();
      }
    });

    this.jQuery('.gjs-am-assets-cont').find('.pagination-holder').append(showNext);
    showNext.on('click', function () {
      if (AssetManager.getAll().length >= 30) {
        pager.val(parseInt(pager.val()) + 1);
        form.find('.form-actions .form-submit').click();
      }
    });
    form.find('.form-actions .form-submit').click();
  }

  delete(id) {
    return Drupal.restconsumer.delete('/media/' + id).done(function () {
      jQuery('.gjs-am-assets-header form .form-actions .form-submit').click();
    });
  }
}

/**
 * Initializes the Pagedesigner Media Manager and add it to the Grapes editor object.
 */
(function (jQuery, Drupal) {

  /**
   *
   */
  jQuery(document).on('submit', '.pd-asset-form form', function (e) {
    e.preventDefault();

    Drupal.restconsumer.submit(jQuery(this), { 'op': jQuery(this).find('[name=op]').val() }, '', {
      success: function () { return true; },
      complete: function () { return true; }
    }).done(function (response) {
      jQuery('.gjs-am-assets-header form .form-actions .form-submit').click();
    });
    jQuery('.pd-asset-form').remove();
  })

  Drupal.behaviors.pagedesigner_media_manager = {
    attach: function (context, settings) {
      jQuery(document).on('pagedesigner-init-traits', function (e, editor) {
        editor.PDMediaManager = new PagedesignerMediaManager(editor, jQuery);
      });
    }
  };
})(jQuery, Drupal);
