"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getMeterScalePosition = getMeterScalePosition;
exports.getMeterGeometry = getMeterGeometry;
exports.getMeterSolidFillColor = getMeterSolidFillColor;
exports.getMeterGradientFill = getMeterGradientFill;
exports.getMeterRevealWindow = getMeterRevealWindow;
const chroma_js_1 = __importDefault(require("chroma-js"));
const d3_scale_1 = require("d3-scale");
const common_1 = require("../../utils/common");
function getScalePositionFn(domain) {
    const [domainStart, domainEnd] = (0, common_1.sortNumbers)(domain);
    if (domainStart === domainEnd) {
        return () => 50;
    }
    const scale = (0, d3_scale_1.scaleLinear)().domain([domainStart, domainEnd]).range([0, 100]);
    return (value) => scale(value);
}
function getMeterScalePosition(domain, value) {
    return getScalePositionFn(domain)(value);
}
function getMeterGeometry(domain, value, baseline = 0) {
    const getScalePosition = getScalePositionFn(domain);
    const rawBaselinePosition = getScalePosition(baseline);
    const rawValuePosition = getScalePosition(value);
    const [fillStart, fillEnd] = (0, common_1.sortNumbers)([(0, common_1.clamp)(rawBaselinePosition, 0, 100), (0, common_1.clamp)(rawValuePosition, 0, 100)]);
    const [domainMin, domainMax] = (0, common_1.sortNumbers)(domain);
    return {
        fillStart,
        fillEnd,
        fillSize: fillEnd - fillStart,
        rawValuePosition,
        rawBaselinePosition,
        isBaselineInDomain: baseline >= domainMin && baseline <= domainMax,
    };
}
function dedupeStopsByPosition(stops) {
    return stops.reduce((acc, stop) => {
        const last = acc.at(-1);
        if (last && last.position === stop.position) {
            acc[acc.length - 1] = stop;
        }
        else {
            acc.push(stop);
        }
        return acc;
    }, []);
}
function getNormalizedMeterColorStops(domain, colorStops) {
    const getScalePosition = getScalePositionFn(domain);
    const normalizedStops = colorStops
        .map(({ color, stop }) => ({
        color,
        position: (0, common_1.clamp)(getScalePosition(stop), 0, 100),
    }))
        .sort((left, right) => left.position - right.position);
    return dedupeStopsByPosition(normalizedStops);
}
function getExtendedMeterColorStops(domain, colorStops) {
    const normalizedStops = getNormalizedMeterColorStops(domain, colorStops);
    const first = normalizedStops[0];
    const last = normalizedStops.at(-1);
    if (!first || !last) {
        return [];
    }
    return [
        ...(first.position > 0 ? [{ color: first.color, position: 0 }] : []),
        ...normalizedStops,
        ...(last.position < 100 ? [{ color: last.color, position: 100 }] : []),
    ];
}
function getMeterSolidFillColor(domain, colorStops, value, fallbackColor) {
    const normalizedStops = getNormalizedMeterColorStops(domain, colorStops);
    if (normalizedStops.length === 0) {
        return fallbackColor;
    }
    if (normalizedStops.length === 1) {
        return normalizedStops[0].color;
    }
    const position = (0, common_1.clamp)(getMeterScalePosition(domain, value), 0, 100);
    const scale = chroma_js_1.default
        .scale(normalizedStops.map(({ color }) => color))
        .mode('lab')
        .domain(normalizedStops.map(({ position: stopPosition }) => stopPosition));
    return scale(position).hex();
}
function getMeterGradientFill(domain, colorStops, orientation) {
    const extendedStops = getExtendedMeterColorStops(domain, colorStops);
    if (extendedStops.length === 0) {
        return undefined;
    }
    const direction = orientation === common_1.LayoutDirection.Vertical ? 'to top' : 'to right';
    return `linear-gradient(${direction}, ${extendedStops
        .map(({ color, position }) => `${color} ${position}%`)
        .join(', ')})`;
}
function getMeterRevealWindow(fillStart, fillSize) {
    if (fillSize <= 0) {
        return undefined;
    }
    return {
        scaleFactor: 100 / fillSize,
        offset: (-fillStart / fillSize) * 100,
    };
}
//# sourceMappingURL=utils.js.map