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

//

/**
 * Based on 2-way merge algorithm from wiki: https://en.wikipedia.org/wiki/K-way_merge_algorithm
 * @template T
 * @param {T[]} a
 * @param {T[]} b
 * @param {function(a:T,b:T):number} compare
 * @returns {{uniqueA:T[], uniqueB:T[], common:T[]}}
 */
export function array_set_diff_sorting(a, b, compare) {
    assert.isFunction(compare, 'compare');

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

    // sort both a and b
    uniqueA.sort(compare);
    uniqueB.sort(compare);

    const common = [];

    let length_a = uniqueA.length;
    let length_b = uniqueB.length;

    let i;
    let j;
    let cursor_j = 0;

    for (i = 0; i < length_a; i++) {
        const el_a = uniqueA[i];

        for (j = cursor_j; j < length_b; j++) {
            const el_b = uniqueB[j];

            const diff = compare(el_a, el_b);

            if (diff === 0) {
                common.push(el_a);

                uniqueA.splice(i, 1);
                uniqueB.splice(j, 1);

                i--;
                j--;

                length_a--;
                length_b--;

            } else if (diff > 0) {
                cursor_j++;
            } else {
                // too far
                break;
            }
        }

    }

    return {
        uniqueA,
        uniqueB,
        common
    };
}
