/*
 * 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/>.
 */
import {groupBy, groupByStable, groupByProperty} from '../src/index.js';
import {expect} from 'chai';

describe('groupBy', () => {
  it('should group an array by a key', () => {
    const array = [
      {id: 1, name: 'one'},
      {id: 2, name: 'two'},
      {id: 3, name: 'three'},
      {id: 4, name: 'four'},
      {id: 5, name: 'five'},
    ];

    const result = groupBy(array, it => it.name);

    expect(result).to.deep.equal({
      one: [{id: 1, name: 'one'}],
      two: [{id: 2, name: 'two'}],
      three: [{id: 3, name: 'three'}],
      four: [{id: 4, name: 'four'}],
      five: [{id: 5, name: 'five'}],
    });
  });

  it('should handle multiple elements per group', () => {
    const array = [
      {id: 1, name: 'one'},
      {id: 2, name: 'two'},
      {id: 3, name: 'three'},
      {id: 4, name: 'four'},
      {id: 5, name: 'five'},
      {id: 6, name: 'one'},
      {id: 7, name: 'two'},
      {id: 8, name: 'three'},
      {id: 9, name: 'four'},
      {id: 10, name: 'five'},
    ];

    const result = groupBy(array, it => it.name);

    expect(result).to.deep.equal({
      one: [
        {id: 1, name: 'one'},
        {id: 6, name: 'one'},
      ],
      two: [
        {id: 2, name: 'two'},
        {id: 7, name: 'two'},
      ],
      three: [
        {id: 3, name: 'three'},
        {id: 8, name: 'three'},
      ],
      four: [
        {id: 4, name: 'four'},
        {id: 9, name: 'four'},
      ],
      five: [
        {id: 5, name: 'five'},
        {id: 10, name: 'five'},
      ],
    });
  });
});

describe('groupByStable', () => {
  const array = [
    {id: 2, name: 'two'},
    {id: 4, name: 'three'},
    {id: 3, name: 'three'},
    {id: 1, name: 'one'},
  ];
  const result = groupByStable(array, it => it.name);

  it('should group an array by keys', () => {
    expect(result.get('one')).to.deep.equal([{id: 1, name: 'one'}]);
    expect(result.get('two')).to.deep.equal([{id: 2, name: 'two'}]);
    expect(result.get('three')).to.deep.equal([
      {id: 4, name: 'three'},
      {id: 3, name: 'three'},
    ]);
  });

  it('should provide ordered keys', () => {
    // eslint-disable-next-line unicorn/prefer-spread
    expect(Array.from(result.keys())).to.deep.equal(['two', 'three', 'one']);
  });
});

describe('groupByProperty', function () {
  it('should group by property', () => {
    const array = [
      {id: 1, name: 'one'},
      {id: 2, name: 'two'},
      {id: 3, name: 'three'},
      {id: 4, name: 'four'},
      {id: 5, name: 'five'},
    ];

    const result = groupByProperty(array, 'name');

    expect(result).to.deep.equal({
      one: [{id: 1, name: 'one'}],
      two: [{id: 2, name: 'two'}],
      three: [{id: 3, name: 'three'}],
      four: [{id: 4, name: 'four'}],
      five: [{id: 5, name: 'five'}],
    });
  });
});
