"use strict";

/**
 * The UI for an administration dashboard widget.
 *
 * This can be subclassed by widgets in order to add custom widget actions and
 * content. Subclasses can render the widget by overriding
 * :js:func:`RB.Admin.WidgetView.renderWidget()`, and respond to layout and
 * size changes by overriding :js:func:`RB.Admin.WidgetView.updateSize()`.
 */
RB.Admin.WidgetView = Backbone.View.extend({
  events: {
    'click .js-action-reload': 'reloadContent'
  },
  /** Whether this widget can reload its contents on request. */
  canReload: false,
  /** Whether this widget can reload its contents on request. */
  reloadTitle: null,
  /**
   * Initialize the widget.
   */
  initialize() {
    this.$header = null;
    this.$content = null;
    this.$footer = null;
    this.$headerActions = null;
    this.$footerActions = null;
    this._$reloadAction = null;
  },
  /**
   * Add an action to the header.
   *
   * Args:
   *     options (object):
   *         Options for the action.
   *
   * Option Args:
   *     id (string):
   *         The ID of the action. This will be used to add a CSS class
   *         in the form of :samp:`js-action-{id}`.
   *
   *     cssClasses (string, optional):
   *         A space-separated list of CSS class names to add to the
   *         action.
   *
   *     el (Element or jQuery, optional):
   *         An optional element to add to the action. This takes
   *         precedence over ``html`` and ``text``.
   *
   *     html (string, optional):
   *         Optional HTML to insert into the action. This takes
   *         precedence over ``text``.
   *
   *     text (string, optional):
   *         Optional plain text to set inside the action.
   *
   *     title (string, optional):
   *         Optional title to display when hovering over the action,
   *         or for screen readers.
   *
   * Returns:
   *     jQuery:
   *     The resulting action element.
   */
  addHeaderAction(options) {
    return this._buildAction(options).appendTo(this.$headerActions);
  },
  /**
   * Add an action to the footer.
   *
   * Args:
   *     options (object):
   *         Options for the action.
   *
   * Option Args:
   *     id (string):
   *         The ID of the action. This will be used to add a CSS class
   *         in the form of :samp:`js-action-{id}`.
   *
   *     cssClasses (string, optional):
   *         A space-separated list of CSS class names to add to the
   *         action.
   *
   *     el (Element or jQuery, optional):
   *         An optional element to add to the action. This takes
   *         precedence over ``html`` and ``text``.
   *
   *     html (string, optional):
   *         Optional HTML to insert into the action. This takes
   *         precedence over ``text``.
   *
   *     text (string, optional):
   *         Optional plain text to set inside the action.
   *
   *     title (string, optional):
   *         Optional title to display when hovering over the action,
   *         or for screen readers.
   *
   * Returns:
   *     jQuery:
   *     The resulting action element.
   */
  addFooterAction(options) {
    return this._buildAction(options).appendTo(this.$footerActions);
  },
  /**
   * Show to the user whether or not content is loading/reloading.
   *
   * This will set whether the reloading action icon is spinning.
   *
   * Args:
   *     reloading (boolean):
   *         Whether to show to the user that content is reloading.
   */
  setReloading(reloading) {
    console.assert(this.canReload, 'This widget did not set canReload=true.');
    this._$reloadAction.toggleClass('fa-spin', reloading);
  },
  /**
   * Render the widget.
   *
   * Returns:
   *     RB.Admin.WidgetView:
   *     This widget, for chaining purposes.
   */
  render() {
    this.$header = this.$el.children('.rb-c-admin-widget__header');
    this.$content = this.$el.children('.rb-c-admin-widget__content');
    this.$footer = this.$el.children('.rb-c-admin-widget__footer');
    this.$headerActions = this.$header.children('.rb-c-admin-widget__actions');
    this.$footerActions = this.$footer.children('.rb-c-admin-widget__actions');
    if (this.canReload) {
      this._$reloadAction = this.addHeaderAction({
        id: 'reload',
        cssClasses: 'fa fa-refresh',
        title: this.reloadTitle
      });
    }
    this.renderWidget();

    /* This is needed only for legacy widgets. */
    this.$el.trigger('widget-shown');
    return this;
  },
  /**
   * Render the content of the widget.
   *
   * This will only be called once, when the widget is first rendered. It
   * should take care of any initial content shown in the widget, and should
   * attach any event listeners needed to perform updates to the content.
   */
  renderWidget() {},
  /**
   * Update the rendered size of the widget.
   *
   * This may be called in response to changes in the widget size, such as
   * when manually resizing the page or switching between desktop and mobile
   * modes.
   *
   * This should perform any changes needed to the rendered size of any
   * non-responsive UI elements in the widget.
   */
  updateSize() {},
  /**
   * Reload the content inside the widget.
   *
   * This is called in response to a user clicking the Reload action,
   * if :js:attr:`RB.Admin.WidgetView.canReload` is set to ``true``.
   */
  reloadContent() {},
  /**
   * Build an action.
   *
   * Args:
   *     options (object):
   *         Options for the action.
   *
   * Option Args:
   *     id (string):
   *         The ID of the action. This will be used to add a CSS class
   *         in the form of :samp:`js-action-{id}`.
   *
   *     cssClasses (string, optional):
   *         A space-separated list of CSS class names to add to the
   *         action.
   *
   *     el (Element or jQuery, optional):
   *         An optional element to add to the action. This takes
   *         precedence over ``html`` and ``text``.
   *
   *     html (string, optional):
   *         Optional HTML to insert into the action. This takes
   *         precedence over ``text``.
   *
   *     text (string, optional):
   *         Optional plain text to set inside the action.
   *
   *     title (string, optional):
   *         Optional title to display when hovering over the action,
   *         or for screen readers.
   *
   * Returns:
   *     jQuery:
   *     The resulting action element.
   */
  _buildAction(options) {
    console.assert(options.id, 'An "id" value must be provided');
    const $action = $('<li class="rb-c-admin-widget__action">').addClass(`js-action-${options.id}`);
    if (options.cssClasses) {
      $action.addClass(options.cssClasses);
    }
    if (options.el) {
      $action.append(options.el);
    } else if (options.html) {
      $action.html(options.html);
    } else if (options.text) {
      $action.text(options.text);
    }
    if (options.title) {
      $action.attr('title', options.title);
    }
    return $action;
  }
});

//# sourceMappingURL=widgetView.js.map