/**
 * @license
 * Copyright 2016 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import '../../../test/common-test-setup';
import '../gr-diff/gr-diff';
import './gr-diff-cursor';
import {fixture, html, assert} from '@open-wc/testing';
import {mockPromise, queryAll, queryAndAssert} from '../../../test/test-utils';
import {createDiff} from '../../../test/test-data-generators';
import {createDefaultDiffPrefs} from '../../../constants/constants';
import {GrDiffCursor} from './gr-diff-cursor';
import {waitForEventOnce} from '../../../utils/event-util';
import {DiffInfo, DiffViewMode, Side} from '../../../api/diff';
import {GrDiff} from '../gr-diff/gr-diff';
import {assertIsDefined} from '../../../utils/common-util';

suite('gr-diff-cursor tests', () => {
  let cursor: GrDiffCursor;
  let diffElement: GrDiff;
  let diff: DiffInfo;

  setup(async () => {
    diffElement = await fixture(html`<gr-diff></gr-diff>`);
    cursor = new GrDiffCursor();

    // Register the diff with the cursor.
    cursor.replaceDiffs([diffElement]);

    diffElement.loggedIn = false;
    diffElement.path = 'some/path.ts';
    const promise = mockPromise();
    const setupDone = () => {
      cursor._updateStops();
      cursor.moveToFirstChunk();
      diffElement.removeEventListener('render', setupDone);
      promise.resolve();
    };
    diffElement.addEventListener('render', setupDone);

    diff = createDiff();
    diffElement.prefs = createDefaultDiffPrefs();
    diffElement.diff = diff;
    await promise;
  });

  test('diff cursor functionality (side-by-side)', () => {
    // The cursor has been initialized to the first delta.
    assert.isOk(cursor.diffRow);

    const firstDeltaRow = queryAndAssert<HTMLElement>(
      diffElement,
      '.section.delta .diff-row'
    );
    assert.equal(cursor.diffRow, firstDeltaRow);

    cursor.moveDown();

    assert.isOk(firstDeltaRow.nextElementSibling);
    assert.notEqual(cursor.diffRow, firstDeltaRow);
    assert.equal(
      cursor.diffRow,
      firstDeltaRow.nextElementSibling as HTMLElement
    );

    cursor.moveUp();

    assert.isOk(firstDeltaRow.nextElementSibling);
    assert.notEqual(
      cursor.diffRow,
      firstDeltaRow.nextElementSibling as HTMLElement
    );
    assert.equal(cursor.diffRow, firstDeltaRow);
  });

  test('moveToFirstChunk', async () => {
    const diff: DiffInfo = {
      meta_a: {
        name: 'lorem-ipsum.txt',
        content_type: 'text/plain',
        lines: 3,
      },
      meta_b: {
        name: 'lorem-ipsum.txt',
        content_type: 'text/plain',
        lines: 3,
      },
      intraline_status: 'OK',
      change_type: 'MODIFIED',
      diff_header: [
        'diff --git a/lorem-ipsum.txt b/lorem-ipsum.txt',
        'index b2adcf4..554ae49 100644',
        '--- a/lorem-ipsum.txt',
        '+++ b/lorem-ipsum.txt',
      ],
      content: [
        {b: ['new line 1']},
        {ab: ['unchanged line']},
        {a: ['old line 2']},
        {ab: ['more unchanged lines']},
      ],
    };

    diffElement.diff = diff;
    // The file comment button, if present, is a cursor stop. Ensure
    // moveToFirstChunk() works correctly even if the button is not shown.
    diffElement.prefs!.show_file_comment_button = false;
    await waitForEventOnce(diffElement, 'render');

    cursor._updateStops();

    const chunks = [
      ...queryAll(diffElement, '.section.delta'),
    ] as HTMLElement[];
    assert.equal(chunks.length, 2);

    // Verify it works on fresh diff.
    cursor.moveToFirstChunk();
    assert.ok(cursor.diffRow);
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 0);
    assert.equal(cursor.side, Side.RIGHT);

    // Verify it works from other cursor positions.
    cursor.moveToNextChunk();
    assert.ok(cursor.diffRow);
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 1);
    assert.equal(cursor.side, Side.LEFT);
    cursor.moveToFirstChunk();
    assert.ok(cursor.diffRow);
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 0);
    assert.equal(cursor.side, Side.RIGHT);
  });

  test('moveToLastChunk', async () => {
    const diff: DiffInfo = {
      meta_a: {
        name: 'lorem-ipsum.txt',
        content_type: 'text/plain',
        lines: 3,
      },
      meta_b: {
        name: 'lorem-ipsum.txt',
        content_type: 'text/plain',
        lines: 3,
      },
      intraline_status: 'OK',
      change_type: 'MODIFIED',
      diff_header: [
        'diff --git a/lorem-ipsum.txt b/lorem-ipsum.txt',
        'index b2adcf4..554ae49 100644',
        '--- a/lorem-ipsum.txt',
        '+++ b/lorem-ipsum.txt',
      ],
      content: [
        {ab: ['unchanged line']},
        {a: ['old line 2']},
        {ab: ['more unchanged lines']},
        {b: ['new line 3']},
      ],
    };

    diffElement.diff = diff;
    await waitForEventOnce(diffElement, 'render');
    cursor._updateStops();

    const chunks = [...queryAll(diffElement, '.section.delta')];
    assert.equal(chunks.length, 2);

    // Verify it works on fresh diff.
    cursor.moveToLastChunk();
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 1);
    assert.equal(cursor.side, Side.RIGHT);

    // Verify it works from other cursor positions.
    cursor.moveToPreviousChunk();
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 0);
    assert.equal(cursor.side, Side.LEFT);
    cursor.moveToLastChunk();
    assert.equal(chunks.indexOf(cursor.diffRow!.parentElement!), 1);
    assert.equal(cursor.side, Side.RIGHT);
  });

  test('cursor scroll behavior', () => {
    assert.equal(cursor.cursorManager.scrollMode, 'keep-visible');

    diffElement.dispatchEvent(new Event('render-start'));
    assert.isTrue(cursor.cursorManager.focusOnMove);

    window.dispatchEvent(new Event('scroll'));
    assert.equal(cursor.cursorManager.scrollMode, 'never');
    assert.isFalse(cursor.cursorManager.focusOnMove);

    diffElement.dispatchEvent(new Event('render-content'));
    assert.isTrue(cursor.cursorManager.focusOnMove);

    cursor.reInitCursor();
    assert.equal(cursor.cursorManager.scrollMode, 'keep-visible');
  });

  test('moves to selected line', () => {
    const moveToNumStub = sinon.stub(cursor, 'moveToLineNumber');

    diffElement.dispatchEvent(
      new CustomEvent('line-selected', {
        detail: {number: '123', side: Side.RIGHT, path: 'some/file'},
      })
    );

    assert.isTrue(moveToNumStub.called);
    assert.equal(moveToNumStub.lastCall.args[0], 123);
    assert.equal(moveToNumStub.lastCall.args[1], Side.RIGHT);
    assert.equal(moveToNumStub.lastCall.args[2], 'some/file');
  });

  suite('unified diff', () => {
    setup(async () => {
      diffElement.viewMode = DiffViewMode.UNIFIED;
      await waitForEventOnce(diffElement, 'render');
      cursor.reInitCursor();
    });

    test('diff cursor functionality (unified)', () => {
      // The cursor has been initialized to the first delta.
      assert.isOk(cursor.diffRow);

      const firstDeltaRow = queryAndAssert<HTMLElement>(
        diffElement,
        '.section.delta .diff-row'
      );
      assert.equal(cursor.diffRow, firstDeltaRow);

      cursor.moveDown();

      assert.notEqual(cursor.diffRow, firstDeltaRow);
      assert.equal(
        cursor.diffRow,
        firstDeltaRow.nextElementSibling as HTMLElement
      );

      cursor.moveUp();

      assert.notEqual(
        cursor.diffRow,
        firstDeltaRow.nextElementSibling as HTMLElement
      );
      assert.equal(cursor.diffRow, firstDeltaRow);
    });
  });

  test('cursor side functionality', () => {
    // The side only applies to side-by-side mode, which should be the default
    // mode.
    assert.equal(diffElement.viewMode, 'SIDE_BY_SIDE');

    const firstDeltaSection = queryAndAssert<HTMLElement>(
      diffElement,
      '.section.delta'
    );
    const firstDeltaRow = queryAndAssert<HTMLElement>(
      firstDeltaSection,
      '.diff-row'
    );

    // Because the first delta in this diff is on the right, it should be set
    // to the right side.
    assert.equal(cursor.side, Side.RIGHT);
    assert.equal(cursor.diffRow, firstDeltaRow);
    const firstIndex = cursor.cursorManager.index;

    // Move the side to the left. Because this delta only has a right side, we
    // should be moved up to the previous line where there is content on the
    // right. The previous row is part of the previous section.
    cursor.moveLeft();

    assert.equal(cursor.side, Side.LEFT);
    assert.notEqual(cursor.diffRow, firstDeltaRow);
    assert.equal(cursor.cursorManager.index, firstIndex - 1);
    assert.equal(
      cursor.diffRow!.parentElement,
      firstDeltaSection.previousSibling
    );

    // If we move down, we should skip everything in the first delta because
    // we are on the left side and the first delta has no content on the left.
    cursor.moveDown();

    assert.equal(cursor.side, Side.LEFT);
    assert.notEqual(cursor.diffRow, firstDeltaRow);
    assert.isTrue(cursor.cursorManager.index > firstIndex);
    assert.equal(cursor.diffRow!.parentElement, firstDeltaSection.nextSibling);
  });

  test('chunk skip functionality', () => {
    const chunks = [...queryAll(diffElement, '.section.delta')];
    const indexOfChunk = function (chunk: HTMLElement) {
      return Array.prototype.indexOf.call(chunks, chunk);
    };

    // We should be initialized to the first chunk. Since this chunk only has
    // content on the right side, our side should be right.
    let currentIndex = indexOfChunk(cursor.diffRow!.parentElement!);
    assert.equal(currentIndex, 0);
    assert.equal(cursor.side, Side.RIGHT);

    // Move to the next chunk.
    cursor.moveToNextChunk();

    // Since this chunk only has content on the left side. we should have been
    // automatically moved over.
    const previousIndex = currentIndex;
    currentIndex = indexOfChunk(cursor.diffRow!.parentElement!);
    assert.equal(currentIndex, previousIndex + 1);
    assert.equal(cursor.side, Side.LEFT);
  });

  suite('moved chunks without line range)', () => {
    setup(async () => {
      const promise = mockPromise();
      const renderHandler = function () {
        diffElement.removeEventListener('render', renderHandler);
        cursor.reInitCursor();
        promise.resolve();
      };
      diffElement.addEventListener('render', renderHandler);
      diffElement.diff = {
        ...diff,
        content: [
          {
            ab: ['Lorem ipsum dolor sit amet, suspendisse inceptos vehicula, '],
          },
          {
            b: [
              'Nullam neque, ligula ac, id blandit.',
              'Sagittis tincidunt torquent, tempor nunc amet.',
              'At rhoncus id.',
            ],
            move_details: {changed: false},
          },
          {
            ab: ['Sem nascetur, erat ut, non in.'],
          },
          {
            a: [
              'Nullam neque, ligula ac, id blandit.',
              'Sagittis tincidunt torquent, tempor nunc amet.',
              'At rhoncus id.',
            ],
            move_details: {changed: false},
          },
          {
            ab: ['Arcu eget, rhoncus amet cursus, ipsum elementum.'],
          },
        ],
      };
      await promise;
    });

    test('renders moveControls with simple descriptions', () => {
      const [movedIn, movedOut] = [
        ...queryAll(diffElement, '.dueToMove .moveControls'),
      ];
      assert.equal(movedIn.textContent, 'Moved in');
      assert.equal(movedOut.textContent, 'Moved out');
    });
  });

  suite('moved chunks (moveDetails)', () => {
    setup(async () => {
      const promise = mockPromise();
      const renderHandler = function () {
        diffElement.removeEventListener('render', renderHandler);
        cursor.reInitCursor();
        promise.resolve();
      };
      diffElement.addEventListener('render', renderHandler);
      diffElement.diff = {
        ...diff,
        content: [
          {
            ab: ['Lorem ipsum dolor sit amet, suspendisse inceptos vehicula, '],
          },
          {
            b: [
              'Nullam neque, ligula ac, id blandit.',
              'Sagittis tincidunt torquent, tempor nunc amet.',
              'At rhoncus id.',
            ],
            move_details: {changed: false, range: {start: 4, end: 6}},
          },
          {
            ab: ['Sem nascetur, erat ut, non in.'],
          },
          {
            a: [
              'Nullam neque, ligula ac, id blandit.',
              'Sagittis tincidunt torquent, tempor nunc amet.',
              'At rhoncus id.',
            ],
            move_details: {changed: false, range: {start: 2, end: 4}},
          },
          {
            ab: ['Arcu eget, rhoncus amet cursus, ipsum elementum.'],
          },
        ],
      };
      await promise;
    });

    test('renders moveControls with simple descriptions', () => {
      const [movedIn, movedOut] = [
        ...queryAll(diffElement, '.dueToMove .moveControls'),
      ];
      assert.equal(movedIn.textContent, 'Moved from lines 4 - 6');
      assert.equal(movedOut.textContent, 'Moved to lines 2 - 4');
    });

    test('startLineAnchor of movedIn chunk fires events', async () => {
      const [movedIn] = [...queryAll(diffElement, '.dueToMove .moveControls')];
      const [startLineAnchor] = movedIn.querySelectorAll('a');

      const promise = mockPromise();
      const onMovedLinkClicked = (e: CustomEvent) => {
        assert.deepEqual(e.detail, {lineNum: 4, side: Side.LEFT});
        promise.resolve();
      };
      assert.equal(startLineAnchor.textContent, '4');
      startLineAnchor.addEventListener(
        'moved-link-clicked',
        onMovedLinkClicked
      );
      startLineAnchor.click();
      await promise;
    });

    test('endLineAnchor of movedOut fires events', async () => {
      const [, movedOut] = [
        ...queryAll(diffElement, '.dueToMove .moveControls'),
      ];
      const [, endLineAnchor] = movedOut.querySelectorAll('a');

      const promise = mockPromise();
      const onMovedLinkClicked = (e: CustomEvent) => {
        assert.deepEqual(e.detail, {lineNum: 4, side: Side.RIGHT});
        promise.resolve();
      };
      assert.equal(endLineAnchor.textContent, '4');
      endLineAnchor.addEventListener('moved-link-clicked', onMovedLinkClicked);
      endLineAnchor.click();
      await promise;
    });
  });

  test('initialLineNumber not provided', async () => {
    let scrollBehaviorDuringMove;
    const moveToNumStub = sinon.stub(cursor, 'moveToLineNumber');
    const moveToChunkStub = sinon
      .stub(cursor, 'moveToFirstChunk')
      .callsFake(() => {
        scrollBehaviorDuringMove = cursor.cursorManager.scrollMode;
      });
    diffElement.diff = createDiff();
    await diffElement.updateComplete;
    await waitForEventOnce(diffElement, 'render');
    cursor.reInitCursor();
    assert.isFalse(moveToNumStub.called);
    assert.isTrue(moveToChunkStub.called);
    assert.equal(scrollBehaviorDuringMove, 'never');
    assert.equal(cursor.cursorManager.scrollMode, 'keep-visible');
  });

  test('initialLineNumber provided', async () => {
    let scrollBehaviorDuringMove;
    const moveToNumStub = sinon
      .stub(cursor, 'moveToLineNumber')
      .callsFake(() => {
        scrollBehaviorDuringMove = cursor.cursorManager.scrollMode;
      });
    const moveToChunkStub = sinon.stub(cursor, 'moveToFirstChunk');
    cursor.initialLineNumber = 10;
    cursor.side = Side.RIGHT;

    diffElement.diff = createDiff();
    await diffElement.updateComplete;
    await waitForEventOnce(diffElement, 'render');
    cursor.reInitCursor();
    assert.isFalse(moveToChunkStub.called);
    assert.isTrue(moveToNumStub.called);
    assert.equal(moveToNumStub.lastCall.args[0], 10);
    assert.equal(moveToNumStub.lastCall.args[1], Side.RIGHT);
    assert.equal(scrollBehaviorDuringMove, 'keep-visible');
    assert.equal(cursor.cursorManager.scrollMode, 'keep-visible');
  });

  test('getTargetDiffElement', () => {
    cursor.initialLineNumber = 1;
    assert.isTrue(!!cursor.diffRow);
    assert.equal(cursor.getTargetDiffElement(), diffElement);
  });

  suite('createCommentInPlace', () => {
    setup(() => {
      diffElement.loggedIn = true;
    });

    test('adds new draft for selected line on the left', async () => {
      cursor.moveToLineNumber(2, Side.LEFT);
      const promise = mockPromise();
      diffElement.addEventListener('create-comment', e => {
        const {lineNum, range, side} = e.detail;
        assert.equal(lineNum, 2);
        assert.equal(range, undefined);
        assert.equal(side, Side.LEFT);
        promise.resolve();
      });
      cursor.createCommentInPlace();
      await promise;
    });

    test('adds draft for selected line on the right', async () => {
      cursor.moveToLineNumber(4, Side.RIGHT);
      const promise = mockPromise();
      diffElement.addEventListener('create-comment', e => {
        const {lineNum, range, side} = e.detail;
        assert.equal(lineNum, 4);
        assert.equal(range, undefined);
        assert.equal(side, Side.RIGHT);
        promise.resolve();
      });
      cursor.createCommentInPlace();
      await promise;
    });

    test('creates comment for range if selected', async () => {
      const someRange = {
        start_line: 2,
        start_character: 3,
        end_line: 6,
        end_character: 1,
      };
      diffElement.highlights.selectedRange = {
        side: Side.RIGHT,
        range: someRange,
      };
      const promise = mockPromise();
      diffElement.addEventListener('create-comment', e => {
        const {lineNum, range, side} = e.detail;
        assert.equal(lineNum, 6);
        assert.equal(range, someRange);
        assert.equal(side, Side.RIGHT);
        promise.resolve();
      });
      cursor.createCommentInPlace();
      await promise;
    });

    test('ignores call if nothing is selected', () => {
      const createRangeCommentStub = sinon.stub(
        diffElement,
        'createRangeComment'
      );
      const addDraftAtLineStub = sinon.stub(diffElement, 'addDraftAtLine');
      cursor.diffRow = undefined;
      cursor.createCommentInPlace();
      assert.isFalse(createRangeCommentStub.called);
      assert.isFalse(addDraftAtLineStub.called);
    });
  });

  test('getAddress', () => {
    // It should initialize to the first chunk: line 5 of the revision.
    assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 5});

    // Revision line 4 is up.
    cursor.moveUp();
    assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 4});

    // Base line 4 is left.
    cursor.moveLeft();
    assert.deepEqual(cursor.getAddress(), {leftSide: true, number: 4});

    // Moving to the next chunk takes it back to the start.
    cursor.moveToNextChunk();
    assert.deepEqual(cursor.getAddress(), {leftSide: false, number: 5});

    // The following chunk is a removal starting on line 10 of the base.
    cursor.moveToNextChunk();
    assert.deepEqual(cursor.getAddress(), {leftSide: true, number: 10});

    // Should be null if there is no selection.
    cursor.cursorManager.unsetCursor();
    assert.isNotOk(cursor.getAddress());
  });

  test('_findRowByNumberAndFile', () => {
    // Get the first ab row after the first chunk.
    const rows = [...queryAll<HTMLTableRowElement>(diffElement, 'tr')];
    const row = rows[9];
    assert.ok(row);

    // It should be line 8 on the right, but line 5 on the left.
    assert.equal(cursor._findRowByNumberAndFile(8, Side.RIGHT), row);
    assert.equal(cursor._findRowByNumberAndFile(5, Side.LEFT), row);
  });

  test('expand context updates stops', async () => {
    const spy = sinon.spy(cursor, '_updateStops');
    const controls = queryAndAssert(diffElement, 'gr-context-controls');
    const showContext = queryAndAssert<HTMLElement>(controls, '.showContext');
    showContext.click();
    await waitForEventOnce(diffElement, 'render');
    assert.isTrue(spy.called);
  });

  test('updates stops when loading changes', () => {
    const spy = sinon.spy(cursor, '_updateStops');
    diffElement.dispatchEvent(new Event('loading-changed'));
    assert.isTrue(spy.called);
  });

  suite('multi diff', () => {
    let diffElements: GrDiff[];

    setup(async () => {
      diffElements = [
        await fixture(html`<gr-diff></gr-diff>`),
        await fixture(html`<gr-diff></gr-diff>`),
        await fixture(html`<gr-diff></gr-diff>`),
      ];
      cursor = new GrDiffCursor();

      // Register the diff with the cursor.
      cursor.replaceDiffs(diffElements);

      for (const el of diffElements) {
        el.prefs = createDefaultDiffPrefs();
      }
    });

    function getTargetDiffIndex() {
      // Mocha has a bug where when `assert.equals` fails, it will try to
      // JSON.stringify the operands, which fails when they are cyclic structures
      // like GrDiffElement. The failure is difficult to attribute to a specific
      // assertion because of the async nature assertion errors are handled and
      // can cause the test simply timing out, causing a lot of debugging headache.
      // Working with indices circumvents the problem.
      const target = cursor.getTargetDiffElement();
      assertIsDefined(target);
      return diffElements.indexOf(target);
    }

    test('do not skip loading diffs', async () => {
      diffElements[0].diff = createDiff();
      diffElements[2].diff = createDiff();
      await waitForEventOnce(diffElements[0], 'render');
      await waitForEventOnce(diffElements[2], 'render');

      const lastLine = diffElements[0].diff.meta_b?.lines;
      assertIsDefined(lastLine);

      // Goto second last line of the first diff
      cursor.moveToLineNumber(lastLine - 1, Side.RIGHT);
      assert.equal(
        cursor.getTargetLineElement()!.textContent,
        `${lastLine - 1}`
      );

      // Can move down until we reach the loading file
      cursor.moveDown();
      assert.equal(getTargetDiffIndex(), 0);
      assert.equal(
        cursor.getTargetLineElement()!.textContent,
        lastLine.toString()
      );

      // Cannot move down while still loading the diff we would switch to
      cursor.moveDown();
      assert.equal(getTargetDiffIndex(), 0);
      assert.equal(
        cursor.getTargetLineElement()!.textContent,
        lastLine.toString()
      );

      // Diff 1 finishing to load
      diffElements[1].diff = createDiff();
      await waitForEventOnce(diffElements[1], 'render');

      // Now we can go down
      cursor.moveDown();
      assert.equal(getTargetDiffIndex(), 1);
      assert.equal(cursor.getTargetLineElement()!.textContent, 'File');
    });
  });
});
