<!--
Copyright (C) 2016 The Android Open Source Project

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script>
(function(window) {
  'use strict';

  // Tags identifying ChangeMessages that move change into WIP state.
  const WIP_TAGS = [
    'autogenerated:gerrit:newWipPatchSet',
    'autogenerated:gerrit:setWorkInProgress',
  ];

  // Tags identifying ChangeMessages that move change out of WIP state.
  const READY_TAGS = [
    'autogenerated:gerrit:setReadyForReview',
  ];

  window.Gerrit = window.Gerrit || {};

  /** @polymerBehavior this */
  Gerrit.PatchSetBehavior = {
    EDIT_NAME: 'edit',

    /**
     * As patchNum can be either a string (e.g. 'edit', 'PARENT') OR a number,
     * this function checks for patchNum equality.
     *
     * @param {string|number} a
     * @param {string|number} b
     */
    patchNumEquals(a, b) {
      return a + '' === b + '';
    },
    /**
     * Given an object of revisions, get a particular revision based on patch
     * num.
     *
     * @param {Object} revisions The object of revisions given by the API
     * @param {number|string} patchNum The number index of the revision
     * @return {Object} The correspondent revision obj from {revisions}
     */
    getRevisionByPatchNum(revisions, patchNum) {
      for (const rev of Object.values(revisions || {})) {
        if (Gerrit.PatchSetBehavior.patchNumEquals(rev._number, patchNum)) {
          return rev;
        }
      }
    },

    /**
     * Find change edit base revision if change edit exists.
     *
     * @param {!Array<!Object>} revisions The revisions array.
     * @return {Object} change edit parent revision or null if change edit
     *     doesn't exist.
     */
    findEditParentRevision(revisions) {
      const editInfo =
          revisions.find(info => info._number ===
              Gerrit.PatchSetBehavior.EDIT_NAME);

      if (!editInfo) { return null; }

      return revisions.find(info => info._number === editInfo.basePatchNum) ||
          null;
    },

    /**
     * Find change edit base patch set number if change edit exists.
     *
     * @param {!Array<!Object>} revisions The revisions array.
     * @return {number} Change edit patch set number or -1.
     */
    findEditParentPatchNum(revisions) {
      const revisionInfo =
          Gerrit.PatchSetBehavior.findEditParentRevision(revisions);
      return revisionInfo ? revisionInfo._number : -1;
    },

    /**
     * Sort given revisions array according to the patch set number. The sort
     * algorithm is change edit aware. Change edit has patch set number equals
     * 0, but must appear after the patch set it was based on. Example: change
     * edit is based on patch set 2, and another patch set was uploaded after
     * change edit creation, the sorted order should be: 1, 2, (0|edit), 3.
     *
     * @param {!Array<!Object>} revisions The revisions array
     * @return {!Array<!Object>} The sorted {revisions} array
     */
    sortRevisions(revisions) {
      const editParent =
          Gerrit.PatchSetBehavior.findEditParentPatchNum(revisions);
      // Map a normal patchNum to 2 * (patchNum - 1) + 1... I.e. 1 -> 1,
      // 2 -> 3, 3 -> 5, etc.
      // Map an edit to the patchNum of parent*2... I.e. edit on 2 -> 4.
      const num = r => r._number === Gerrit.PatchSetBehavior.EDIT_NAME ?
          2 * editParent :
          2 * (r._number - 1) + 1;
      return revisions.sort((a, b) => num(a) - num(b));
    },

    /**
     * Construct a chronological list of patch sets derived from change details.
     * Each element of this list is an object with the following properties:
     *
     *   * num {number} The number identifying the patch set
     *   * desc {!string} Optional patch set description
     *   * wip {boolean} If true, this patch set was never subject to review.
     *
     * The wip property is determined by the change's current work_in_progress
     * property and its log of change messages.
     *
     * @param {!Object} change The change details
     * @return {!Array<!Object>} Sorted list of patch set objects, as described
     *     above
     */
    computeAllPatchSets(change) {
      if (!change) { return []; }
      let patchNums = [];
      if (change.revisions &&
          Object.keys(change.revisions).length) {
        patchNums =
          Gerrit.PatchSetBehavior.sortRevisions(Object.values(change.revisions))
              .map(e => {
                // TODO(kaspern): Mark which patchset an edit was made on, if an
                // edit exists -- perhaps with a temporary description.
                return {
                  num: e._number,
                  desc: e.description,
                };
              });
      }
      patchNums.sort((a, b) => { return a.num - b.num; });
      return Gerrit.PatchSetBehavior._computeWipForPatchSets(change, patchNums);
    },

    /**
     * Populate the wip properties of the given list of patch sets.
     *
     * @param {!Object} change The change details
     * @param {!Array<!Object>} patchNums Sorted list of patch set objects, as
     *     generated by computeAllPatchSets
     * @return {!Array<!Object>} The given list of patch set objects, with the
     *     wip property set on each of them
     */
    _computeWipForPatchSets(change, patchNums) {
      if (!change.messages || !change.messages.length) {
        return patchNums;
      }
      const psWip = {};
      let wip = change.work_in_progress;
      for (let i = 0; i < change.messages.length; i++) {
        const msg = change.messages[i];
        if (WIP_TAGS.includes(msg.tag)) {
          wip = true;
        } else if (READY_TAGS.includes(msg.tag)) {
          wip = false;
        }
        if (psWip[msg._revision_number] !== false) {
          psWip[msg._revision_number] = wip;
        }
      }

      for (let i = 0; i < patchNums.length; i++) {
        patchNums[i].wip = psWip[patchNums[i].num];
      }
      return patchNums;
    },

    computeLatestPatchNum(allPatchSets) {
      if (!allPatchSets || !allPatchSets.length) { return undefined; }
      if (allPatchSets[allPatchSets.length - 1].num ===
          Gerrit.PatchSetBehavior.EDIT_NAME) {
        return allPatchSets[allPatchSets.length - 2].num;
      }
      return allPatchSets[allPatchSets.length - 1].num;
    },

    /**
     * Check whether there is no newer patch than the latest patch that was
     * available when this change was loaded.
     *
     * @return {Promise<boolean>} A promise that yields true if the latest patch
     *     has been loaded, and false if a newer patch has been uploaded in the
     *     meantime. The promise is rejected on network error.
     */
    fetchIsLatestKnown(change, restAPI) {
      const knownLatest = Gerrit.PatchSetBehavior.computeLatestPatchNum(
          Gerrit.PatchSetBehavior.computeAllPatchSets(change));
      return restAPI.getChangeDetail(change._number)
          .then(detail => {
            if (!detail) {
              return Promise.reject('Unable to check for latest patchset.');
            }
            const actualLatest = Gerrit.PatchSetBehavior.computeLatestPatchNum(
                Gerrit.PatchSetBehavior.computeAllPatchSets(detail));
            return actualLatest <= knownLatest;
          });
    },

    /**
     * @param {number|string} patchNum
     * @param {!Array<!Object>} revisions A sorted array of revisions.
     *
     * @return {number} The index of the revision with the given patchNum.
     */
    findSortedIndex(patchNum, revisions) {
      revisions = revisions || [];
      const findNum = rev => rev._number + '' === patchNum + '';
      return revisions.findIndex(findNum);
    },
  };
})(window);
</script>
