"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getYDatumValueFn = getYDatumValueFn;
exports.isDatumFilled = isDatumFilled;
exports.getClippedRanges = getClippedRanges;
exports.getGeometryStateStyle = getGeometryStateStyle;
exports.isPointOnGeometry = isPointOnGeometry;
exports.isLineAreaPointWithinPanel = isLineAreaPointWithinPanel;
exports.isYValueDefinedFn = isYValueDefinedFn;
exports.getY1ScaledValueFn = getY1ScaledValueFn;
exports.getY0ScaledValueFn = getY0ScaledValueFn;
const types_1 = require("../../../scales/types");
const specs_1 = require("../../../specs");
const common_1 = require("../../../utils/common");
const geometry_1 = require("../../../utils/geometry");
function getYDatumValueFn(valueName = 'y1') {
    return (datum, returnFilled = true) => {
        const value = datum[valueName];
        if (value !== null || !returnFilled) {
            return value;
        }
        return datum.filled?.[valueName] ?? null;
    };
}
function isDatumFilled({ filled, initialY1 }) {
    return filled?.x !== undefined || filled?.y1 !== undefined || initialY1 === null || initialY1 === undefined;
}
function getClippedRanges(dataset, xScale, xScaleOffset) {
    let firstNonNullX = null;
    let hasNull = false;
    const completeDatasetIsNull = dataset.every((datum) => isDatumFilled(datum));
    if (completeDatasetIsNull)
        return [[xScale.range[0], xScale.range[1]]];
    return dataset.reduce((acc, data) => {
        const xScaled = xScale.scale(data.x);
        if (Number.isNaN(xScaled))
            return acc;
        const xValue = xScaled - xScaleOffset + xScale.bandwidth / 2;
        if (isDatumFilled(data)) {
            const endXValue = xScale.range[1] - xScale.bandwidth * (2 / 3);
            if (firstNonNullX !== null && xValue === endXValue) {
                acc.push([firstNonNullX, xValue]);
            }
            hasNull = true;
        }
        else {
            if (hasNull) {
                if (firstNonNullX !== null) {
                    acc.push([firstNonNullX, xValue]);
                }
                else {
                    acc.push([0, xValue]);
                }
                hasNull = false;
            }
            firstNonNullX = xValue;
        }
        return acc;
    }, []);
}
function getGeometryStateStyle(seriesIdentifier, sharedGeometryStyle, highlightedLegendItem) {
    if (highlightedLegendItem) {
        const isHighlighted = highlightedLegendItem.seriesIdentifiers.some((si) => si.key === seriesIdentifier.key);
        return isHighlighted ? sharedGeometryStyle.highlighted : sharedGeometryStyle.unhighlighted;
    }
    return sharedGeometryStyle.default;
}
function isPointOnGeometry(xCoordinate, yCoordinate, indexedGeometry, buffer) {
    const { x, y, transform } = indexedGeometry;
    if ((0, geometry_1.isPointGeometry)(indexedGeometry)) {
        const { radius } = indexedGeometry;
        const distance = (0, common_1.getDistance)({
            x: xCoordinate,
            y: yCoordinate,
        }, {
            x: x + transform.x,
            y: y + transform.y,
        });
        const radiusBuffer = typeof buffer === 'number' ? buffer : buffer(radius);
        return distance <= radius + radiusBuffer;
    }
    const { width, height } = indexedGeometry;
    if (!(0, common_1.isWithinRange)([x, x + width])(xCoordinate))
        return false;
    return (0, common_1.isWithinRange)([y, y + height])(yCoordinate);
}
function isLineAreaPointWithinPanel(spec, indexedGeometry) {
    const isLineOrAreaPoint = (0, geometry_1.isPointGeometry)(indexedGeometry) && ((0, specs_1.isLineSeriesSpec)(spec) || (0, specs_1.isAreaSeriesSpec)(spec));
    if (!isLineOrAreaPoint)
        return false;
    const { x, y, transform } = indexedGeometry;
    const { width, height } = indexedGeometry.panel;
    const gx = x + transform.x;
    const gy = y + transform.y;
    if (!(0, common_1.isWithinRange)([0, width])(gx))
        return false;
    return (0, common_1.isWithinRange)([0, height])(gy);
}
const getScaleTypeValueValidator = (yScale) => {
    if (!(0, types_1.isLogarithmicScale)(yScale))
        return () => true;
    const domainPolarity = getDomainPolarity(yScale.domain);
    return (yValue) => domainPolarity === Math.sign(yValue);
};
const DEFAULT_ZERO_BASELINE = 0;
function isYValueDefinedFn(yScale, xScale) {
    const validator = getScaleTypeValueValidator(yScale);
    return (datum, getValueAccessor) => {
        const yValue = getValueAccessor(datum);
        return yValue !== null && validator(yValue) && xScale.isValueInDomain(datum.x);
    };
}
function getY1ScaledValueFn(yScale) {
    const datumAccessor = getYDatumValueFn();
    return (datum) => {
        return yScale.scale(datumAccessor(datum));
    };
}
function getY0ScaledValueFn(yScale) {
    const domainPolarity = getDomainPolarity(yScale.domain);
    const logBaseline = domainPolarity >= 0 ? Math.min(...yScale.domain) : Math.max(...yScale.domain);
    return ({ y0 }) => (0, types_1.isLogarithmicScale)(yScale)
        ? y0 === null || domainPolarity !== Math.sign(y0)
            ? yScale.scale(logBaseline)
            : yScale.scale(y0)
        : yScale.scale(y0 === null ? DEFAULT_ZERO_BASELINE : y0);
}
function getDomainPolarity(domain) {
    return Math.sign(Math.sign(domain[0] ?? NaN) + Math.sign(domain[1] ?? NaN));
}
//# sourceMappingURL=utils.js.map