import { returnZero } from "../../function/returnZero.js";
import { HashMap } from "../map/HashMap.js";

/**
 * @template T,K
 * @param {T[]} array
 * @param {function(T):K} grouping_key_producer given an element from input array, returns a grouping key. Can be an object, if it implements .equals method keys can be compared that way as well
 * @param keyHashFunction
 * @returns {Map<K,T[]>}
 */
export function array_group_by(array, grouping_key_producer, keyHashFunction = returnZero) {
    const result = new HashMap({
        keyHashFunction,
        keyEqualityFunction(a, b) {
            if (a === b) {
                return true;
            }

            if (typeof a === "object" && a !== null && typeof a.equals === "function") {
                return a.equals(b);
            }

            return false;
        }
    });

    for (let i = 0; i < array.length; i++) {
        const element = array[i];

        const groupKey = grouping_key_producer(element);

        const group = result.get(groupKey);

        if (group === undefined) {
            result.set(groupKey, [element]);
        } else {
            group.push(element);
        }
    }

    return result;
}
