"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressBar = void 0;
exports.getMetricProgressBarSize = getMetricProgressBarSize;
exports.getMetricProgressBarThickness = getMetricProgressBarThickness;
const classnames_1 = __importDefault(require("classnames"));
const d3_scale_1 = require("d3-scale");
const react_1 = __importDefault(require("react"));
const color_calcs_1 = require("../../../../common/color_calcs");
const color_library_wrappers_1 = require("../../../../common/color_library_wrappers");
const meter_1 = require("../../../../components/meter");
const common_1 = require("../../../../utils/common");
const specs_1 = require("../../specs");
const DEFAULT_PROGRESS_VALUE_LABELS = {
    value: 'Value',
    target: 'Target',
};
function hasExplicitProgressDomain(datum) {
    return (0, specs_1.isBulletMetric)(datum) || datum.domainMin !== undefined;
}
function getMetricProgressBarSize(progressBarThickness) {
    switch (progressBarThickness) {
        case 4:
            return meter_1.MeterSize.Small;
        case 8:
            return meter_1.MeterSize.Medium;
        case 16:
            return meter_1.MeterSize.Large;
        default:
            return meter_1.MeterSize.Small;
    }
}
function getMetricProgressBarThickness(size) {
    switch (size) {
        case meter_1.MeterSize.Small:
            return 4;
        case meter_1.MeterSize.Medium:
            return 8;
        case meter_1.MeterSize.Large:
            return 16;
        default:
            return undefined;
    }
}
function blendMetricProgressColor(color, backgroundColor) {
    return (0, color_library_wrappers_1.RGBATupleToString)((0, color_calcs_1.combineColors)((0, color_library_wrappers_1.colorToRgba)(color), (0, color_library_wrappers_1.colorToRgba)(backgroundColor)));
}
function resolveMetricProgressBarFill(fill, fallbackColor, backgroundColor) {
    if (!fill) {
        return { type: meter_1.MeterFillStyle.Single, color: fallbackColor };
    }
    if (fill.type === meter_1.MeterFillStyle.Single) {
        return {
            ...fill,
            color: blendMetricProgressColor(fill.color, backgroundColor),
        };
    }
    return {
        ...fill,
        colorStops: fill.colorStops.map((stop) => ({
            ...stop,
            color: blendMetricProgressColor(stop.color, backgroundColor),
        })),
        fallbackColor: fill.fallbackColor === undefined ? undefined : blendMetricProgressColor(fill.fallbackColor, backgroundColor),
    };
}
function mirrorDomainValue(domain, value) {
    const [domainMin, domainMax] = (0, common_1.sortNumbers)(domain);
    return domainMin + domainMax - value;
}
function reverseMetricProgressBarFill(fill, domain) {
    if (fill.type === meter_1.MeterFillStyle.Single) {
        return fill;
    }
    return {
        ...fill,
        colorStops: fill.colorStops.map((stop) => ({
            ...stop,
            stop: mirrorDomainValue(domain, stop.stop),
        })),
    };
}
const ProgressBar = ({ datum, barBackground, panelBackground, fillBackgroundColor, blendedBarColor, size, fill, }) => {
    const { title, value, target, valueFormatter, targetFormatter, progressBarDirection } = datum;
    const hasExplicitDomain = hasExplicitProgressDomain(datum);
    const isVertical = progressBarDirection === common_1.LayoutDirection.Vertical;
    const domain = (0, specs_1.isBulletMetric)(datum) ? datum.domain : [datum.domainMin ?? 0, datum.domainMax];
    const scale = (0, d3_scale_1.scaleLinear)().domain(domain).range([0, 100]);
    if ((0, specs_1.isBulletMetric)(datum) && datum.niceDomain) {
        scale.nice();
    }
    const updatedDomain = scale.domain();
    const isReversedBulletDomain = (0, specs_1.isBulletMetric)(datum) && updatedDomain[0] > updatedDomain[1];
    const [domainMin, domainMax] = (0, common_1.sortNumbers)(updatedDomain);
    const scaledValue = (0, common_1.clamp)(scale(value), 0, 100);
    const roundedScaledValue = Math.round(scaledValue * 100) / 100;
    const hasZeroBaselineMarker = domainMin < 0 && domainMax > 0;
    const progressValueLabels = hasExplicitDomain
        ? (0, specs_1.isBulletMetric)(datum)
            ? datum.valueLabels
            : datum.progressValueLabels ?? DEFAULT_PROGRESS_VALUE_LABELS
        : undefined;
    const labelType = progressValueLabels?.value ?? 'Percentage';
    const progressBarFill = resolveMetricProgressBarFill(fill, blendedBarColor, fillBackgroundColor);
    const meterDomain = isReversedBulletDomain ? (0, common_1.sortNumbers)(updatedDomain) : updatedDomain;
    const meterValue = isReversedBulletDomain ? mirrorDomainValue(updatedDomain, value) : value;
    const meterBaseline = isReversedBulletDomain ? mirrorDomainValue(updatedDomain, 0) : 0;
    const meterTarget = isReversedBulletDomain && !(0, common_1.isNil)(target) ? mirrorDomainValue(updatedDomain, target) : target;
    const meterFill = isReversedBulletDomain
        ? reverseMetricProgressBarFill(progressBarFill, updatedDomain)
        : progressBarFill;
    return (react_1.default.createElement(meter_1.Meter, { value: meterValue, domain: meterDomain, fill: meterFill, trackColor: barBackground, orientation: progressBarDirection, size: size, baseline: meterBaseline, target: meterTarget, markerColor: fill ? undefined : blendedBarColor, fillBorderColor: panelBackground, fillBorderWidth: 2, showBaselineMarker: hasZeroBaselineMarker, roundTrackStart: true, roundTrackEnd: true, roundFillStart: !hasZeroBaselineMarker, roundFillEnd: true, className: getDirectionalClasses('Progress', isVertical, size), title: progressValueLabels ? `${updatedDomain[0]} to ${updatedDomain[1]}` : '', valueTitle: progressValueLabels ? `${progressValueLabels.value}: ${valueFormatter(value)}` : `${roundedScaledValue}%`, targetTitle: (0, common_1.isNil)(target)
            ? undefined
            : `${progressValueLabels ? `${progressValueLabels.target}: ` : ''}${(targetFormatter ?? valueFormatter)(target)}`, ariaLabel: title ? `${labelType} of ${title}` : labelType, ariaValueMin: progressValueLabels ? domainMin : 0, ariaValueMax: progressValueLabels ? domainMax : 100, ariaValueNow: progressValueLabels ? value : roundedScaledValue, ariaValueText: progressValueLabels ? valueFormatter(value) : `${roundedScaledValue}%` }));
};
exports.ProgressBar = ProgressBar;
function getDirectionalClasses(element, isVertical, progressBarSize) {
    const base = `echSingleMetric${element}`;
    return (0, classnames_1.default)(base, `${base}--${progressBarSize}`, {
        [`${base}--vertical`]: isVertical,
        [`${base}--horizontal`]: !isVertical,
    });
}
//# sourceMappingURL=progress.js.map