"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.weightedAverage = exports.getNumericValue = void 0;
const tslib_1 = require("tslib");
const toNumber_1 = tslib_1.__importDefault(require("./utils/toNumber"));
const getNumericValue = (input) => {
    if (typeof input === 'number') {
        return input;
    }
    const numericValue = (0, toNumber_1.default)(input);
    return isNaN(numericValue) ? null : numericValue;
};
exports.getNumericValue = getNumericValue;
/**
 * Computes a weighted average aggregation: Σ(value × weight) / Σ(weight)
 *
 * AG Grid calls agg functions bottom-up through the group hierarchy. For each group:
 * - Leaf children contribute their raw value × weight
 * - Sub-group children already have partial sums from a previous pass,
 *   so we combine those directly instead of re-traversing to leaves
 *
 * The returned object stores partial sums ([columnId] and [weightColumnId])
 * so parent groups can combine sub-group results correctly.
 */
const weightedAverage = (params, columnId, weightColumnId) => {
    const { api: gridApi, rowNode: groupRowNode, values } = params;
    // numerator: Σ(value × weight)
    let weightedValueSum = 0;
    // denominator: Σ(weight)
    let totalWeight = 0;
    // params.values already respects suppressAggFilteredOnly.
    // We need the matching child nodes only for leaf rows (to look up weight column values).
    const childNodes = getMatchingChildNodes(groupRowNode, values.length);
    for (let i = 0; i < values.length; i++) {
        const value = values[i];
        if (value != null && typeof value === 'object') {
            // sub-group: partial sums already computed by a previous aggregation pass
            weightedValueSum += value[columnId] ?? 0;
            totalWeight += value[weightColumnId] ?? 0;
        }
        else {
            // leaf row: compute value × weight from cell data
            const childNode = childNodes[i];
            if (!childNode) {
                continue;
            }
            // values might be strings during editing
            const columnValue = (0, exports.getNumericValue)(value);
            const weightValue = (0, exports.getNumericValue)(gridApi.getCellValue({ colKey: weightColumnId, rowNode: childNode }));
            if (weightValue !== null) {
                totalWeight += weightValue;
            }
            if (columnValue !== null && weightValue !== null) {
                weightedValueSum += columnValue * weightValue;
            }
        }
    }
    const result = totalWeight !== 0 ? weightedValueSum / totalWeight : 0;
    return {
        // toString/toNumber let AG Grid's default cell renderer display and sort the value
        toString: () => String(result),
        toNumber: () => result,
        // partial sums stored so parent groups can combine sub-group results
        [columnId]: weightedValueSum,
        [weightColumnId]: totalWeight,
    };
};
exports.weightedAverage = weightedAverage;
/**
 * Returns the child node list that corresponds to params.values.
 * When suppressAggFilteredOnly is false, params.values comes from childrenAfterFilter.
 * When true, it comes from childrenAfterGroup (all children).
 * We match by length to pick the right list without checking the grid option directly.
 */
function getMatchingChildNodes(groupRowNode, valueCount) {
    if (groupRowNode.childrenAfterFilter?.length === valueCount) {
        return groupRowNode.childrenAfterFilter;
    }
    return groupRowNode.childrenAfterGroup ?? [];
}
