import {
  insertAtIndex,
  moveToIndex,
  pushToArray,
  removeAtIndex,
  replaceAtIndex,
  swapElements,
} from '@/graphql/immutable-operations.ts';

describe('Cache operations', () => {
  it('removes at index', () => {
    const original = [1, 2, 3];
    const copy = removeAtIndex(original, 1);
    expect(original.length).toBe(3);
    expect(original).toEqual([1, 2, 3]);
    expect(copy.length).toBe(2);
    expect(copy).toEqual([1, 3]);

    original.push(4);
    expect(original.length).toBe(4);
    expect(original).toEqual([1, 2, 3, 4]);
    expect(copy.length).toBe(2);
    expect(copy).toEqual([1, 3]);
  });

  it('replaces at index', () => {
    const original = [1, 2, 3];
    const copy = replaceAtIndex(original, 1, 234);
    expect(original.length).toBe(3);
    expect(original).toEqual([1, 2, 3]);
    expect(copy.length).toBe(3);
    expect(copy).toEqual([1, 234, 3]);

    original.push(4);
    expect(original.length).toBe(4);
    expect(original).toEqual([1, 2, 3, 4]);
    expect(copy.length).toBe(3);
    expect(copy).toEqual([1, 234, 3]);
  });

  it('inserts at index', () => {
    const original = [1, 2, 3];
    const copy = insertAtIndex(original, 1, 234);
    expect(original.length).toBe(3);
    expect(original).toEqual([1, 2, 3]);
    expect(copy.length).toBe(4);
    expect(copy).toEqual([1, 234, 2, 3]);

    original.push(4);
    expect(original.length).toBe(4);
    expect(original).toEqual([1, 2, 3, 4]);
    expect(copy.length).toBe(4);
    expect(copy).toEqual([1, 234, 2, 3]);
  });

  it('pushed to array', () => {
    const original = [1, 2, 3];
    const copy = pushToArray(original, 5);
    expect(original.length).toBe(3);
    expect(original).toEqual([1, 2, 3]);
    expect(copy.length).toBe(4);
    expect(copy).toEqual([1, 2, 3, 5]);

    original.push(4);
    expect(original.length).toBe(4);
    expect(original).toEqual([1, 2, 3, 4]);
    expect(copy.length).toBe(4);
    expect(copy).toEqual([1, 2, 3, 5]);
  });

  it('swaps elements of array', () => {
    const original = [1, 2, 3];
    const copy = swapElements(original, 0, 2);
    expect(original.length).toBe(3);
    expect(original).toEqual([1, 2, 3]);
    expect(copy.length).toBe(3);
    expect(copy).toEqual([3, 2, 1]);

    original.push(4);
    expect(original.length).toBe(4);
    expect(original).toEqual([1, 2, 3, 4]);
    expect(copy.length).toBe(3);
    expect(copy).toEqual([3, 2, 1]);
  });

  it('swaps neighbors', () => {
    const original = [1, 2, 3, 4, 5];
    const copy = swapElements(original, 3, 2);

    expect(copy).toEqual([1, 2, 4, 3, 5]);
  });

  it('does nothing with wrong indices', () => {
    const original = [1, 2, 3, 4, 5];
    const copy1 = swapElements(original, -1, 2);
    const copy2 = swapElements(original, 1, 99);
    const copy3 = swapElements(original, 1, 5);

    expect(copy1).toEqual([1, 2, 3, 4, 5]);
    expect(copy2).toEqual([1, 2, 3, 4, 5]);
    expect(copy3).toEqual([1, 2, 3, 4, 5]);
    original.push(4);
    expect(original.length).toBe(6);
    expect(copy1.length).toBe(5);
    expect(copy2.length).toBe(5);
    expect(copy3.length).toBe(5);
  });

  it('moves to a specific index', () => {
    const original = [1, 2, 3, 4, 5, 6, 7];
    const toStart = moveToIndex(original, 3, 0);
    const toEnd = moveToIndex(original, 3, original.length - 1);
    const toMiddle = moveToIndex(original, 3, 2);

    expect(toStart).toEqual([4, 1, 2, 3, 5, 6, 7]);
    expect(toEnd).toEqual([1, 2, 3, 5, 6, 7, 4]);
    expect(toMiddle).toEqual([1, 2, 4, 3, 5, 6, 7]);
  });
});
