import { assert } from "../../assert.js";

import { strictEquals } from "../../function/strictEquals.js";
import { array_index_by_equality } from "./array_index_by_equality.js";

/**
 * Compute a diff between two arrays, result is a 3 way split between common items, unique items in `a` array and unique items in `b` array
 * @see prefer to use {@link array_set_diff_sorting}, as it's much faster, especially for large sets
 * @template T
 * @param {T[]} a
 * @param {T[]} b
 * @param {function(a:T,b:T):boolean} [equals] method to determine equality between two elements
 * @returns {{uniqueA:T[], uniqueB:T[], common:T[]}}
 */
export function array_set_diff(a, b, equals = strictEquals) {
    assert.isArray(a, 'a');
    assert.isArray(b, 'b');
    assert.isFunction(equals, 'equals');

    const uniqueA = a.slice();
    const uniqueB = b.slice();

    const common = [];

    let a_length = uniqueA.length;

    for (let i = 0; i < a_length; i++) {
        const elA = uniqueA[i];

        const j = array_index_by_equality(uniqueB, elA, equals);

        if (j !== -1) {
            // common element found

            common.push(elA);

            // remove from respective unique sets
            uniqueA.splice(i, 1);
            uniqueB.splice(j, 1);

            i--;
            a_length--;
        }
    }

    return {
        uniqueA,
        uniqueB,
        common
    };
}

