"use strict";

/*
 * The templates should be kept in sync with:
 *
 * - templates/reviews/changedesc_commit_list.html
 * - templates/reviews/commit_list_field.html
 *
 * so that they render items identically.
 */
(function () {
  const itemTemplate = _.template(`<tr class="rb-c-commit-list__commit <%- rowClass || '' %>">
 <% if (showHistorySymbol) { %>
  <td class="rb-c-commit-list__op" aria-label="<%- opLabel %>"></td>
 <% } else if (showInterCommitDiffControls) { %>
  <td class="rb-c-commit-list__select-base">
   <input type="radio"
          class="base-commit-selector"
          name="base-commit-id"
          aria-label="<%- baseSelectorLabel %>"
          <% if (baseSelected) { %>checked<% } %>
          <% if (baseDisabled) { %>disabled<% } %>
          value="<%- commit.id %>">
  </td>
  <td class="rb-c-commit-list__select-tip">
   <input type="radio"
          class="tip-commit-selector"
          name="tip-commit-id"
          aria-label="<%- tipSelectorLabel %>"
          <% if (tipSelected) { %>checked<% } %>
          <% if (tipDisabled) { %>disabled<% } %>
          value="<%- commit.id %>">
  </td>
 <% } %>
 <% if (commit) { %>
  <td class="rb-c-commit-list__message">
   <% if (commitBody) { %>
    <details>
     <summary class="rb-c-commit-list__message-summary"><%-
      commitSummary
     %></summary>
     <div class="rb-c-commit-list__message-body"><%- commitBody %></div>
    </details>
   <% } else { %>
    <div class="rb-c-commit-list__message-summary"><%-
     commitSummary
    %></div>
   <% } %>
  </td>
  <td class="rb-c-commit-list__id"
      title="<%- commitID %>"><%- commitID %></td>
  <td class="rb-c-commit-list__author"><%- commitAuthor %></td>
 <% } else { %>
  <td class="rb-c-commit-list__message"></td>
  <td class="rb-c-commit-list__id"></td>
  <td class="rb-c-commit-list__author"></td>
 <% } %>
</tr>`);
  const headerTemplate = _.template(`<thead>
 <tr>
  <% if (showHistorySymbol) { %>
   <th class="rb-c-commit-list__column-op"></th>
  <% } else if (showInterCommitDiffControls) { %>
   <th class="rb-c-commit-list__column-select-tip"><%- firstText %></th>
   <th class="rb-c-commit-list__column-select-base"><%- lastText %></th>
  <% } %>
  <th class="rb-c-commit-list__column-summary"><%- summaryText %></th>
  <th class="rb-c-commit-list__column-id"><%- idText %></th>
  <th class="rb-c-commit-list__column-author"><%- authorText %></th>
 </tr>
</thead>`);
  const tableTemplate = _.template(`<form class="rb-c-review-request-field-tabular rb-c-commit-list">
 <table class="rb-c-review-request-field-tabular__data"></table>
</form>`);

  /**
   * A view for displaying a list of commits and their metadata.
   */
  RB.DiffCommitListView = Backbone.View.extend({
    events: {
      'change .base-commit-selector': '_onBaseChanged',
      'change .tip-commit-selector': '_onTipChanged'
    },
    /**
     * Initialize the view.
     *
     * Args:
     *     options (object):
     *         Options that control how this view behaves.
     *
     * Option Args:
     *     showInterCommitDiffControls (boolean):
     *         Whether or not to show interdiff controls.
     */
    initialize(options) {
      this.listenTo(this.model.get('commits'), 'reset', this.render);
      this._showInterCommitDiffControls = !!options.showInterCommitDiffControls;
      this._$baseSelectors = $();
      this._$tipSelectors = $();
    },
    /**
     * Render the view.
     *
     * Returns:
     *     RB.DiffCommitListView:
     *     This view, for chaining.
     */
    render() {
      const commits = this.model.get('commits');
      const isInterdiff = this.model.isInterdiff();
      const commonContext = {
        baseSelectorLabel: gettext("Set first commit"),
        showHistorySymbol: isInterdiff,
        showInterCommitDiffControls: this._showInterCommitDiffControls,
        tipSelectorLabel: gettext("Set last commit")
      };
      const $content = $(tableTemplate(commonContext));
      const $table = $content.find('.rb-c-review-request-field-tabular__data').append(headerTemplate(_.extend({
        authorText: gettext("Author"),
        firstText: gettext("First"),
        idText: gettext("ID"),
        lastText: gettext("Last"),
        summaryText: gettext("Summary")
      }, commonContext)));
      const $tbody = $('<tbody>');
      if (isInterdiff) {
        this.model.get('historyDiff').each(historyDiffEntry => {
          const entryType = historyDiffEntry.get('entryType');
          let key;
          let rowClass;
          let opLabel;
          switch (entryType) {
            case RB.CommitHistoryDiffEntry.ADDED:
              rowClass = '-is-added';
              key = 'newCommitID';
              opLabel = gettext("Added commit");
              break;
            case RB.CommitHistoryDiffEntry.REMOVED:
              rowClass = '-is-removed';
              key = 'oldCommitID';
              opLabel = gettext("Removed commit");
              break;
            case RB.CommitHistoryDiffEntry.UNMODIFIED:
              key = 'newCommitID';
              opLabel = gettext("Added commit");
              break;
            case RB.CommitHistoryDiffEntry.MODIFIED:
              rowClass = '-is-modified';
              key = 'newCommitID';
              opLabel = gettext("Unmodified commit");
              break;
            default:
              console.error('Invalid history entry type: %s', entryType);
              break;
          }
          const commit = commits.get(historyDiffEntry.get(key));
          $tbody.append(itemTemplate(_.extend({
            historyDiffEntry: historyDiffEntry,
            opLabel: opLabel,
            rowClass: rowClass
          }, this._buildItemCommitContext(commit), commonContext)));
        });
      } else {
        commonContext.rowClass = '';
        const baseCommitID = this.model.get('baseCommitID');
        const tipCommitID = this.model.get('tipCommitID');
        const lastIndex = commits.size() - 1;
        const baseIndex = baseCommitID === null ? 0 : commits.indexOf(commits.getChild(commits.get(baseCommitID)));
        const tipIndex = tipCommitID === null ? lastIndex : commits.indexOf(commits.get(tipCommitID));
        commits.each((commit, i) => {
          $tbody.append(itemTemplate(_.extend({
            baseSelected: i === baseIndex,
            tipSelected: i === tipIndex,
            baseDisabled: i > tipIndex,
            tipDisabled: i < baseIndex
          }, this._buildItemCommitContext(commit), commonContext)));
        });
      }
      $table.append($tbody);
      this.$el.empty().append($content);
      this._$baseSelectors = this.$('.base-commit-selector');
      this._$tipSelectors = this.$('.tip-commit-selector');
      return this;
    },
    /**
     * Return template render context for a commit item.
     *
     * Args:
     *     commit (RB.DiffCommit):
     *         The commit for which to return context.
     *
     * Returns:
     *     object:
     *     The template render context for the item.
     */
    _buildItemCommitContext(commit) {
      let commitAuthor = null;
      let commitID = null;
      let commitSummary = null;
      let commitBody = null;
      if (commit) {
        commitAuthor = commit.get('authorName');
        commitID = commit.get('commitID');
        commitSummary = commit.get('summary');
        commitBody = commit.get('commitMessageBody');
      }
      return {
        commit: commit,
        commitAuthor: commitAuthor,
        commitBody: commitBody,
        commitID: commitID,
        commitSummary: commitSummary
      };
    },
    /**
     * Handle the base commit selection changing.
     *
     * The view's model will be updated to reflect this change.
     *
     * Args:
     *     e (jQuery.Event):
     *         The change event.
     */
    _onBaseChanged(e) {
      const $target = $(e.target);
      const commits = this.model.get('commits');
      const commit = commits.get(parseInt($target.val(), 10));
      const index = commits.indexOf(commit);
      this.model.set('baseCommitID', index === 0 ? null : commits.getParent(commit).id);
      this._$tipSelectors.slice(0, index).prop('disabled', true);
      this._$tipSelectors.slice(index).prop('disabled', false);
    },
    /**
     * Handle the tip commit selection changing.
     *
     * The view's model will be updated to reflect this change.
     *
     * Args:
     *     e (jQuery.Event):
     *         The change event.
     */
    _onTipChanged(e) {
      const $target = $(e.target);
      const commits = this.model.get('commits');
      const commit = commits.get(parseInt($target.val(), 10));
      const index = commits.indexOf(commit);
      this.model.set('tipCommitID', index === commits.size() - 1 ? null : commit.id);
      this._$baseSelectors.slice(0, index + 1).prop('disabled', false);
      this._$baseSelectors.slice(index + 1).prop('disabled', true);
    }
  });
})();

//# sourceMappingURL=diffCommitListView.js.map