/*
 * Copyright (C) 2022 StApps
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, version 3.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */
/* eslint-disable @typescript-eslint/no-explicit-any */
import {groupRangeOverlaps} from './range-overlap';
import {shuffle} from '@openstapps/collection-utils';

interface SimpleRange {
  starty: number;
  endy: number;
}

const from = (range: SimpleRange) => range.starty;
const till = (range: SimpleRange) => range.endy;

describe('RangeOverlaps', () => {
  it('should handle empty ranges', () => {
    expect(groupRangeOverlaps<SimpleRange>([], from, till)).toEqual([]);
  });

  it('should handle single range', () => {
    expect(groupRangeOverlaps<SimpleRange>([{starty: 0, endy: 1}], from, till)).toEqual([
      {start: 0, end: 1, elements: [{starty: 0, endy: 1}]},
    ]);
  });

  it('should handle two non-overlapping ranges', () => {
    expect(
      groupRangeOverlaps<SimpleRange>(
        shuffle([
          {starty: 0, endy: 1},
          {starty: 2, endy: 3},
        ]),
        from,
        till,
      ),
    ).toEqual([
      {start: 0, end: 1, elements: [{starty: 0, endy: 1}]},
      {start: 2, end: 3, elements: [{starty: 2, endy: 3}]},
    ]);
  });

  it('should not overlap two directly adjacent ranges', () => {
    expect(
      groupRangeOverlaps<SimpleRange>(
        shuffle([
          {starty: 0, endy: 1},
          {starty: 1, endy: 2},
        ]),
        from,
        till,
      ),
    ).toEqual([
      {start: 0, end: 1, elements: [{starty: 0, endy: 1}]},
      {start: 1, end: 2, elements: [{starty: 1, endy: 2}]},
    ]);
  });

  it('should handle two overlapping ranges', () => {
    expect(
      groupRangeOverlaps<SimpleRange>(
        shuffle([
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
        ]),
        from,
        till,
      ),
    ).toEqual([
      {
        start: 0,
        end: 3,
        elements: [
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
        ],
      },
    ]);
  });

  it('should handle multiple overlapping ranges', () => {
    expect(
      groupRangeOverlaps<SimpleRange>(
        shuffle([
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
          {starty: 2, endy: 4},
          {starty: 3, endy: 5},
        ]),
        from,
        till,
      ),
    ).toEqual([
      {
        start: 0,
        end: 5,
        elements: [
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
          {starty: 2, endy: 4},
          {starty: 3, endy: 5},
        ],
      },
    ]);
  });

  it('should handle two groups of three overlapping ranges each', () => {
    expect(
      groupRangeOverlaps<SimpleRange>(
        shuffle([
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
          {starty: 2, endy: 4},
          {starty: 5, endy: 7},
          {starty: 6, endy: 8},
          {starty: 7, endy: 9},
        ]),
        from,
        till,
      ),
    ).toEqual([
      {
        start: 0,
        end: 4,
        elements: [
          {starty: 0, endy: 2},
          {starty: 1, endy: 3},
          {starty: 2, endy: 4},
        ],
      },
      {
        start: 5,
        end: 9,
        elements: [
          {starty: 5, endy: 7},
          {starty: 6, endy: 8},
          {starty: 7, endy: 9},
        ],
      },
    ]);
  });
});
