/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../test/common-test-setup-karma';
import {
  createChange,
  createChangeMessageInfo,
  createRevision,
} from '../test/test-data-generators';
import {
  BasePatchSetNum,
  ChangeInfo,
  EDIT,
  PatchSetNum,
  PatchSetNumber,
  ReviewInputTag,
  PARENT,
} from '../types/common';
import {
  _testOnly_computeWipForPatchSets,
  computeAllPatchSets,
  findEditParentPatchNum,
  findEditParentRevision,
  getParentIndex,
  getRevisionByPatchNum,
  isMergeParent,
  sortRevisions,
} from './patch-set-util';

suite('gr-patch-set-util tests', () => {
  test('getRevisionByPatchNum', () => {
    const revisions = [createRevision(0), createRevision(1), createRevision(2)];
    assert.deepEqual(
      getRevisionByPatchNum(revisions, 1 as PatchSetNum),
      revisions[1]
    );
    assert.deepEqual(
      getRevisionByPatchNum(revisions, 2 as PatchSetNum),
      revisions[2]
    );
    assert.equal(getRevisionByPatchNum(revisions, 3 as PatchSetNum), undefined);
  });

  test('_computeWipForPatchSets', () => {
    // Compute patch sets for a given timeline on a change. The initial WIP
    // property of the change can be true or false. The map of tags by
    // revision is keyed by patch set number. Each value is a list of change
    // message tags in the order that they occurred in the timeline. These
    // indicate actions that modify the WIP property of the change and/or
    // create new patch sets.
    //
    // Returns the actual results with an assertWip method that can be used
    // to compare against an expected value for a particular patch set.
    const compute = (
      initialWip: boolean,
      tagsByRevision: Map<PatchSetNumber, (ReviewInputTag | undefined)[]>
    ) => {
      const change: ChangeInfo = {
        ...createChange(),
        messages: [],
        work_in_progress: initialWip,
      };
      for (const rev of tagsByRevision.keys()) {
        for (const tag of tagsByRevision.get(rev)!) {
          change.messages!.push({
            ...createChangeMessageInfo(),
            tag,
            _revision_number: rev,
          });
        }
      }
      const patchSets = Array.from(tagsByRevision.keys()).map(rev => {
        return {num: rev, desc: 'test', sha: `rev${rev}`};
      });
      const patchNums = _testOnly_computeWipForPatchSets(change, patchSets);
      const verifier = {
        assertWip(revision: number, expectedWip: boolean) {
          const patchNum = patchNums.find(
            patchNum => patchNum.num === (revision as PatchSetNum)
          );
          if (!patchNum) {
            assert.fail(`revision ${revision} not found`);
          }
          assert.equal(
            patchNum.wip,
            expectedWip,
            `wip state for ${revision} ` +
              `is ${patchNum.wip}; expected ${expectedWip}`
          );
          return verifier;
        },
      };
      return verifier;
    };

    const upload = 'upload' as ReviewInputTag;

    compute(false, new Map([[1 as PatchSetNumber, [upload]]])).assertWip(
      1,
      false
    );
    compute(true, new Map([[1 as PatchSetNumber, [upload]]])).assertWip(
      1,
      true
    );

    const setWip = 'autogenerated:gerrit:setWorkInProgress' as ReviewInputTag;
    const uploadInWip = 'autogenerated:gerrit:newWipPatchSet' as ReviewInputTag;
    const clearWip = 'autogenerated:gerrit:setReadyForReview' as ReviewInputTag;

    compute(
      false,
      new Map([
        [1 as PatchSetNumber, [upload, setWip]],
        [2 as PatchSetNumber, [upload]],
        [3 as PatchSetNumber, [upload, clearWip]],
        [4 as PatchSetNumber, [upload, setWip]],
      ])
    )
      .assertWip(1, false) // Change was created with PS1 ready for review
      .assertWip(2, true) // PS2 was uploaded during WIP
      .assertWip(3, false) // PS3 was marked ready for review after upload
      .assertWip(4, false); // PS4 was uploaded ready for review

    compute(
      false,
      new Map([
        [
          1 as PatchSetNumber,
          [uploadInWip, undefined, 'addReviewer' as ReviewInputTag],
        ],
        [2 as PatchSetNumber, [upload]],
        [3 as PatchSetNumber, [upload, clearWip, setWip]],
        [4 as PatchSetNumber, [upload]],
        [5 as PatchSetNumber, [upload, clearWip]],
        [6 as PatchSetNumber, [uploadInWip]],
      ])
    )
      .assertWip(1, true) // Change was created in WIP
      .assertWip(2, true) // PS2 was uploaded during WIP
      .assertWip(3, false) // PS3 was marked ready for review
      .assertWip(4, true) // PS4 was uploaded during WIP
      .assertWip(5, false) // PS5 was marked ready for review
      .assertWip(6, true); // PS6 was uploaded with WIP option
  });

  test('isMergeParent', () => {
    assert.isFalse(isMergeParent(1 as PatchSetNum));
    assert.isFalse(isMergeParent(4321 as PatchSetNum));
    assert.isFalse(isMergeParent(EDIT as PatchSetNum));
    assert.isFalse(isMergeParent(PARENT as PatchSetNum));
    assert.isFalse(isMergeParent(0 as PatchSetNum));

    assert.isTrue(isMergeParent(-23 as PatchSetNum));
    assert.isTrue(isMergeParent(-1 as PatchSetNum));
  });

  test('findEditParentRevision', () => {
    const revisions = [createRevision(0), createRevision(1), createRevision(2)];
    assert.strictEqual(findEditParentRevision(revisions), null);

    revisions.push({
      ...createRevision(EDIT),
      basePatchNum: 3 as BasePatchSetNum,
    });
    assert.strictEqual(findEditParentRevision(revisions), null);

    revisions.push(createRevision(3));
    assert.deepEqual(findEditParentRevision(revisions), createRevision(3));
  });

  test('findEditParentPatchNum', () => {
    const revisions = [createRevision(0), createRevision(1), createRevision(2)];
    assert.equal(findEditParentPatchNum(revisions), -1);

    revisions.push(
      {
        ...createRevision(EDIT),
        basePatchNum: 3 as BasePatchSetNum,
      },
      createRevision(3)
    );
    assert.deepEqual(findEditParentPatchNum(revisions), 3);
  });

  test('sortRevisions', () => {
    const revisions = [createRevision(0), createRevision(2), createRevision(1)];
    const sorted = [createRevision(2), createRevision(1), createRevision(0)];

    assert.deepEqual(sortRevisions(revisions), sorted);

    // Edit patchset should follow directly after its basePatchNum.
    revisions.push({
      ...createRevision(EDIT),
      basePatchNum: 2 as BasePatchSetNum,
    });
    sorted.unshift({
      ...createRevision(EDIT),
      basePatchNum: 2 as BasePatchSetNum,
    });
    assert.deepEqual(sortRevisions(revisions), sorted);

    revisions[0].basePatchNum = 0 as BasePatchSetNum;
    const edit = sorted.shift()!;
    edit.basePatchNum = 0 as BasePatchSetNum;
    // Edit patchset should be at index 2.
    sorted.splice(2, 0, edit);
    assert.deepEqual(sortRevisions(revisions), sorted);
  });

  test('getParentIndex', () => {
    assert.equal(getParentIndex(-4 as PatchSetNum), 4);
  });

  test('computeAllPatchSets', () => {
    const expected = [
      {num: 4 as PatchSetNumber, desc: 'test', sha: 'rev4'},
      {num: 3 as PatchSetNumber, desc: 'test', sha: 'rev3'},
      {num: 2 as PatchSetNumber, desc: 'test', sha: 'rev2'},
      {num: 1 as PatchSetNumber, desc: 'test', sha: 'rev1'},
    ];
    const patchNums = computeAllPatchSets({
      ...createChange(),
      revisions: {
        rev1: {...createRevision(1), description: 'test'},
        rev2: {...createRevision(2), description: 'test'},
        rev3: {...createRevision(3), description: 'test'},
        rev4: {...createRevision(4), description: 'test'},
      },
    });
    assert.equal(patchNums.length, expected.length);
    for (let i = 0; i < expected.length; i++) {
      assert.deepEqual(patchNums[i], expected[i]);
    }
  });
});
