// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

import { Settings } from "../types";

export function splitIntoMultiSeries(
    settings: Settings,
    data,
    { stack = false, excludeEmpty = false } = {}
) {
    const useData = data || settings.data;

    if (settings.splitValues.length > 0) {
        return splitByValuesIntoMultiSeries(settings, useData, {
            stack,
            excludeEmpty,
        });
    }
    return [useData];
}

function splitByValuesIntoMultiSeries(
    settings,
    data,
    { stack = false, excludeEmpty = false }
) {
    // Create a series for each "split" value, each one containing all the
    // "aggregate" values, and "base" values to offset it from the previous
    // series
    const multiSeries = {};

    data.forEach((col) => {
        // Split this column by "split", including multiple aggregates for each
        const baseValues = {};
        const split = {};

        // Keys are of the form "split1|split2|aggregate"
        Object.keys(col)
            .filter((key) => key !== "__ROW_PATH__")
            .filter(
                (key) =>
                    !excludeEmpty || (col[key] != null && col[key] != undefined)
            )
            .forEach((key) => {
                const labels = key.split("|");
                // label="aggregate"
                const label = labels[labels.length - 1];
                const value = col[key] || 0;
                const baseKey = `${label}${value >= 0 ? "+ve" : "-ve"}`;
                // splitName="split1|split2"
                const splitName = labels.slice(0, labels.length - 1).join("|");

                // Combine aggregate values for the same split in a single
                // object
                const splitValues = (split[splitName] = split[splitName] || {
                    __ROW_PATH__: col.__ROW_PATH__,
                });
                const baseValue = baseValues[baseKey] || 0;

                splitValues.__KEY__ = splitName;

                // Assign the values for this split/aggregate
                if (stack) {
                    splitValues[label] = baseValue + value;
                    splitValues[`__BASE_VALUE__${label}`] = baseValue;
                    baseValues[baseKey] = splitValues[label];
                } else {
                    splitValues[label] = value;
                }
                splitValues.row = col;
            });

        // Push each object onto the correct series
        Object.keys(split).forEach((splitName) => {
            const series = (multiSeries[splitName] =
                multiSeries[splitName] || []);
            series.push(split[splitName]);
        });
    });

    return Object.keys(multiSeries).map((k) => {
        const series = multiSeries[k];
        series.key = k;
        return series;
    });
}
