module.exports = elementorModules.editor.utils.Module.extend({
  elementType: null,
  __construct(elementType) {
    this.elementType = elementType;
    this.addEditorListener();
  },
  updateOptions(name, options) {
    const controlView = this.getEditorControlView(name);
    if (controlView) {
      this.getEditorControlModel(name).set('options', options);
      controlView.render();
    }
  },
  addEditorListener() {
    var self = this;
    if (self.onElementChange) {
      var eventName = 'change';
      if ('global' !== self.elementType) {
        eventName += ':' + self.elementType;
      }
      elementor.channels.editor.on(eventName, function (controlView, elementView) {
        self.onElementChange(controlView.model.get('name'), controlView, elementView);
      });
    }
  },
  /**
   * Add a spinner to a control inside its control title.
   *
   * @param {string} controlName - The control name to add the spinner to.
   *
   * @return {void}
   */
  addControlSpinner(controlName) {
    const $el = this.getEditorControlView(controlName).$el;

    // Exit if there is a spinner already.
    if ($el.find('.elementor-control-spinner').length) {
      return;
    }
    const $input = $el.find(':input');
    $input.attr('disabled', true);
    $el.find('.elementor-control-title').after('<span class="elementor-control-spinner"><i class="eicon-spinner eicon-animation-spin"></i>&nbsp;</span>');
  },
  /**
   * Remove a spinner from a control.
   *
   * @param {string} controlName - The control name to remove the spinner from.
   *
   * @return {void}
   */
  removeControlSpinner(controlName) {
    const $controlEl = this.getEditorControlView(controlName).$el;
    $controlEl.find(':input').attr('disabled', false);
    $controlEl.find('.elementor-control-spinner').remove();
  },
  /**
   * Add an error message under the control.
   *
   * @param {string} controlName - The control name to add the error to.
   * @param {string} error       - Set an error message.
   * @param {string} location    - A CSS selector to the element which the error will be appended to.
   *
   * @return {void}
   */
  addControlError(controlName, error) {
    let location = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.elementor-control-content';
    const $el = this.getEditorControlView(controlName).$el;

    // Remove any existing error in order to override it.
    if ($el.find('.e-control-error').length) {
      $el.find('.e-control-error').remove();
    }

    // Select only the first elements to prevent cases where the error is added to many elements.
    // (usually in repeater controls).
    $el.find(location).first().after(`<span class="elementor-control-field-description e-control-error">${error}</span>`);
  },
  /**
   * Remove the control error message.
   *
   * @param {string} controlName - The control name to add the error to.
   *
   * @return {void}
   */
  removeControlError(controlName) {
    const $el = this.getEditorControlView(controlName).$el;
    $el.find('.e-control-error').remove();
  },
  /**
   * Remove any indicators that are related to the control. (e.g. spinner, error, etc.)
   *
   * @param {string} controlName - The control name to reset.
   *
   * @return {void}
   */
  resetControlIndicators(controlName) {
    this.removeControlSpinner(controlName);
    this.removeControlError(controlName);
  },
  addSectionListener(section, callback) {
    const self = this;
    elementor.channels.editor.on('section:activated', function (sectionName, editor) {
      var model = editor.getOption('editedElementView').getEditModel(),
        currentElementType = model.get('elType'),
        _arguments = arguments;
      if ('widget' === currentElementType) {
        currentElementType = model.get('widgetType');
      }
      if (self.elementType === currentElementType && section === sectionName) {
        setTimeout(function () {
          callback.apply(self, _arguments);
        }, 10);
      }
    });
  }
});