"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FunnelChartBase = void 0;
var tslib_1 = require("tslib");
var React = require("react");
var Utilities_1 = require("@fluentui/react/lib/Utilities");
var react_focus_1 = require("@fluentui/react-focus");
var index_1 = require("../Legends/index");
var Callout_1 = require("@fluentui/react/lib/Callout");
var ChartHoverCard_1 = require("../../utilities/ChartHoverCard/ChartHoverCard");
var chart_utilities_1 = require("@fluentui/chart-utilities");
var image_export_utils_1 = require("../../utilities/image-export-utils");
var utilities_1 = require("../../utilities/utilities");
var funnelGeometry_1 = require("./funnelGeometry");
var getClassNames = (0, Utilities_1.classNamesFunction)();
exports.FunnelChartBase = React.forwardRef(function (props, forwardedRef) {
    var _a;
    var _tooltipId = (0, Utilities_1.getId)('FunnelChartTooltipId_');
    var _emptyChartId = (0, Utilities_1.getId)('_FunnelChart_empty');
    var isRTL = (0, Utilities_1.getRTL)();
    var _b = React.useState(null), hoveredStage = _b[0], setHoveredStage = _b[1];
    var _c = React.useState(false), isCalloutVisible = _c[0], setIsCalloutVisible = _c[1];
    var _d = React.useState(null), calloutData = _d[0], setCalloutData = _d[1];
    var _e = React.useState(null), refSelected = _e[0], setRefSelected = _e[1];
    var _f = React.useState([]), selectedLegends = _f[0], setSelectedLegends = _f[1];
    var chartContainerRef = React.useRef(null);
    var legendsRef = React.useRef(null);
    var isStacked = isStackedFunnelData(props.data);
    React.useEffect(function () {
        var _a;
        if ((_a = props.legendProps) === null || _a === void 0 ? void 0 : _a.selectedLegends) {
            setSelectedLegends(props.legendProps.selectedLegends);
        }
    }, [(_a = props.legendProps) === null || _a === void 0 ? void 0 : _a.selectedLegends]);
    React.useImperativeHandle(props.componentRef, function () { return ({
        chartContainer: chartContainerRef !== null && chartContainerRef !== void 0 ? chartContainerRef : null,
        toImage: function (opts) {
            var _a;
            return (0, image_export_utils_1.toImage)(chartContainerRef.current, (_a = legendsRef.current) === null || _a === void 0 ? void 0 : _a.toSVG, (0, Utilities_1.getRTL)(), opts);
        },
    }); }, []);
    function _handleHover(data, mouseEvent) {
        mouseEvent === null || mouseEvent === void 0 ? void 0 : mouseEvent.persist();
        setHoveredStage(data.stage);
        setCalloutData(data);
        setIsCalloutVisible(true);
        setRefSelected(mouseEvent.currentTarget);
    }
    function _handleStackedHover(stage, subValue, mouseEvent) {
        mouseEvent === null || mouseEvent === void 0 ? void 0 : mouseEvent.persist();
        setHoveredStage(subValue.category);
        setCalloutData({
            stage: stage,
            value: subValue.value,
            color: subValue.color,
            category: subValue.category,
        });
        setIsCalloutVisible(true);
        setRefSelected(mouseEvent.currentTarget);
    }
    function _handleMouseOut() {
        setHoveredStage(null);
        setIsCalloutVisible(false);
        setCalloutData(null);
        setRefSelected(null);
    }
    function _onLegendSelectionChange(legendsSelected, event, currentLegend) {
        var _a, _b;
        if ((_a = props.legendProps) === null || _a === void 0 ? void 0 : _a.canSelectMultipleLegends) {
            setSelectedLegends(legendsSelected);
        }
        else {
            setSelectedLegends(legendsSelected.slice(-1));
        }
        if ((_b = props.legendProps) === null || _b === void 0 ? void 0 : _b.onChange) {
            props.legendProps.onChange(legendsSelected, event, currentLegend);
        }
    }
    var _onLegendSelectionChangeCallback = React.useCallback(_onLegendSelectionChange, [props.legendProps]);
    function getHighlightedLegend() {
        return selectedLegends.length > 0 ? selectedLegends : hoveredStage ? [hoveredStage] : [];
    }
    function legendHighlighted(legend) {
        return getHighlightedLegend().includes(legend);
    }
    function noLegendHighlighted() {
        return getHighlightedLegend().length === 0;
    }
    function _getEventHandlerProps(data) {
        if ('subValue' in data) {
            return {
                culture: props.culture,
                onMouseOver: function (event) { return _handleStackedHover(data.stage, data.subValue, event); },
                onMouseMove: function (event) { return _handleStackedHover(data.stage, data.subValue, event); },
                onMouseOut: function () { return _handleMouseOut(); },
            };
        }
        else {
            return {
                culture: props.culture,
                onMouseOver: function (event) { return _handleHover(data, event); },
                onMouseMove: function (event) { return _handleHover(data, event); },
                onMouseOut: function () { return _handleMouseOut(); },
            };
        }
    }
    function _renderSegmentText(_a) {
        var show = _a.show, x = _a.x, y = _a.y, value = _a.value, textColor = _a.textColor;
        if (!show) {
            return null;
        }
        var textElement = (React.createElement("text", { x: isRTL ? funnelWidth - x : x, y: y, textAnchor: "middle", alignmentBaseline: "middle", fill: textColor }, (0, chart_utilities_1.formatToLocaleString)(value.toString(), props.culture)));
        if (isRTL) {
            return React.createElement("g", { transform: "scale(-1,1) translate(".concat(-funnelWidth, ",0)") }, textElement);
        }
        return textElement;
    }
    function _renderFunnelSegment(_a) {
        var key = _a.key, pathD = _a.pathD, fill = _a.fill, opacity = _a.opacity, textProps = _a.textProps, data = _a.data;
        var eventHandlers = _getEventHandlerProps(data);
        var textColor = (0, utilities_1.getContrastTextColor)(fill, props.theme);
        return (React.createElement("g", { key: key },
            React.createElement("path", tslib_1.__assign({ d: pathD, fill: fill, opacity: opacity }, eventHandlers)),
            textProps && React.createElement("g", tslib_1.__assign({}, eventHandlers), _renderSegmentText(tslib_1.__assign(tslib_1.__assign({}, textProps), { textColor: textColor })))));
    }
    function _createFunnel(containerHeight, containerWidth) {
        var data = props.data;
        var funnelWidth = containerWidth;
        var funnelHeight = containerHeight * 0.8;
        return data.map(function (d, i) {
            var geometryProps = props.orientation === 'horizontal'
                ? (0, funnelGeometry_1.getHorizontalFunnelSegmentGeometry)({ d: d, i: i, data: data, funnelWidth: funnelWidth, funnelHeight: funnelHeight, isRTL: isRTL })
                : (0, funnelGeometry_1.getVerticalFunnelSegmentGeometry)({ d: d, i: i, data: data, funnelWidth: funnelWidth, funnelHeight: funnelHeight, isRTL: isRTL });
            var pathD = geometryProps.pathD, textX = geometryProps.textX, textY = geometryProps.textY, availableWidth = geometryProps.availableWidth;
            var minTextWidth = 16;
            var eventHandlerProps = _getEventHandlerProps(d);
            var textProps = (0, funnelGeometry_1.getSegmentTextProps)(tslib_1.__assign({ availableWidth: availableWidth, minTextWidth: minTextWidth, textX: textX, textY: textY, value: d.value }, eventHandlerProps));
            return _renderFunnelSegment({
                key: i,
                pathD: pathD,
                fill: d.color,
                opacity: legendHighlighted(d.stage) || noLegendHighlighted() ? 1 : 0.1,
                textProps: textProps,
                data: d,
            });
        });
    }
    function isStackedFunnelData(data) {
        return Array.isArray(data) && data.every(function (stage) { return Array.isArray(stage.subValues); });
    }
    function _renderStackedSegment(stage, subValue, stageIndex, subValueIndex, geometryParams) {
        // Ensure stages have subValues for geometry functions
        var stagesWithSubValues = geometryParams.stages.map(function (s) { return (tslib_1.__assign(tslib_1.__assign({}, s), { subValues: s.subValues || [] })); });
        var geom = props.orientation === 'horizontal'
            ? (0, funnelGeometry_1.getStackedHorizontalFunnelSegmentGeometry)(tslib_1.__assign(tslib_1.__assign({}, geometryParams), { stages: stagesWithSubValues, i: stageIndex, k: subValueIndex }))
            : (0, funnelGeometry_1.getStackedVerticalFunnelSegmentGeometry)(tslib_1.__assign(tslib_1.__assign({}, geometryParams), { stages: stagesWithSubValues, i: stageIndex, k: subValueIndex }));
        var minTextWidth = 16;
        var eventHandlerProps = _getEventHandlerProps({ stage: stage.stage, subValue: subValue });
        var textProps = (0, funnelGeometry_1.getSegmentTextProps)(tslib_1.__assign({ availableWidth: geom.availableWidth, minTextWidth: minTextWidth, textX: geom.textX, textY: geom.textY, value: subValue.value }, eventHandlerProps));
        return _renderFunnelSegment({
            key: "".concat(stageIndex, "-").concat(subValueIndex),
            pathD: geom.pathD,
            fill: subValue.color,
            opacity: (isStackedFunnelData(props.data) && legendHighlighted(subValue.category)) || noLegendHighlighted() ? 1 : 0.1,
            textProps: textProps,
            data: { stage: stage.stage, subValue: subValue },
        });
    }
    function _createStackedFunnel(containerHeight, containerWidth) {
        var _a, _b;
        var data = props.data;
        var stages = data;
        var totals = stages.map(function (s) { var _a, _b; return (_b = (_a = s === null || s === void 0 ? void 0 : s.subValues) === null || _a === void 0 ? void 0 : _a.reduce(function (sum, subValue) { return sum + subValue.value; }, 0)) !== null && _b !== void 0 ? _b : 0; });
        var maxTotal = Math.max.apply(Math, totals);
        var funnelWidth = containerWidth;
        var funnelHeight = containerHeight * 0.8;
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        var paths = [];
        var geometryParams = {
            stages: stages,
            totals: totals,
            maxTotal: maxTotal,
            funnelWidth: funnelWidth,
            funnelHeight: funnelHeight,
            isRTL: isRTL,
        };
        for (var i = 0; i < stages.length; i++) {
            var cur = stages[i];
            for (var k = 0; k < ((_a = cur.subValues) !== null && _a !== void 0 ? _a : []).length; k++) {
                var v = (_b = cur.subValues) === null || _b === void 0 ? void 0 : _b[k];
                if (!v) {
                    continue;
                }
                paths.push(_renderStackedSegment(cur, v, i, k, geometryParams));
            }
        }
        return paths;
    }
    function _renderLegends() {
        if (props.hideLegend) {
            return React.createElement(React.Fragment, null);
        }
        var legends;
        if (isStacked) {
            // Collect unique categories and their color
            var categoryMap_1 = {};
            props.data.forEach(function (stage) {
                (stage.subValues || []).forEach(function (sub) {
                    if (!(sub.category in categoryMap_1)) {
                        categoryMap_1[sub.category] = sub.color;
                    }
                });
            });
            legends = Object.entries(categoryMap_1).map(function (_a) {
                var category = _a[0], color = _a[1];
                return ({
                    title: category,
                    color: color,
                    hoverAction: function () { return setHoveredStage(category); },
                    onMouseOutAction: function () { return setHoveredStage(null); },
                });
            });
        }
        else {
            legends = props.data.map(function (d) { return ({
                title: d.stage,
                color: d.color,
                hoverAction: function () { return setHoveredStage(d.stage); },
                onMouseOutAction: function () { return setHoveredStage(null); },
            }); });
        }
        return (React.createElement("div", { style: { display: 'flex', justifyContent: 'center' } },
            React.createElement(index_1.Legends, tslib_1.__assign({ ref: legendsRef, legends: legends, centerLegends: true, onChange: _onLegendSelectionChangeCallback }, props.legendProps))));
    }
    function _isChartEmpty() {
        return !(props.data && props.data.length > 0);
    }
    var calloutProps = tslib_1.__assign({ isCalloutVisible: isCalloutVisible, directionalHint: Callout_1.DirectionalHint.topAutoEdge, id: "toolTip".concat(_tooltipId), target: refSelected, color: calloutData === null || calloutData === void 0 ? void 0 : calloutData.color, XValue: calloutData === null || calloutData === void 0 ? void 0 : calloutData.stage, YValue: calloutData === null || calloutData === void 0 ? void 0 : calloutData.value, isBeakVisible: false, gapSpace: 15, onDismiss: function () {
            setIsCalloutVisible(false);
        }, preventDismissOnLostFocus: true }, props.calloutProps);
    var width = props.width || 350;
    var height = props.height || 500;
    var classNames = getClassNames(props.styles, {
        theme: props.theme,
        className: props.className,
        chartWidth: width,
        chartHeight: height,
    });
    var funnelMarginTop = 40;
    var funnelWidth = width * 0.8;
    var funnelOffsetX = (width - funnelWidth) / 2;
    return !_isChartEmpty() ? (React.createElement("div", { ref: chartContainerRef, className: classNames.root },
        React.createElement(react_focus_1.FocusZone, { direction: react_focus_1.FocusZoneDirection.horizontal },
            React.createElement("svg", { width: width, height: height, className: classNames.chart, role: 'img', "aria-label": props.chartTitle },
                React.createElement("g", { transform: isRTL
                        ? "translate(".concat(funnelOffsetX + funnelWidth, ", ").concat(funnelMarginTop, ") scale(-1,1)")
                        : "translate(".concat(funnelOffsetX, ", ").concat(funnelMarginTop, ")") }, isStacked
                    ? _createStackedFunnel(height - funnelMarginTop, funnelWidth)
                    : _createFunnel(height - funnelMarginTop, funnelWidth)),
                isCalloutVisible && (React.createElement(Callout_1.Callout, tslib_1.__assign({}, calloutProps),
                    React.createElement(ChartHoverCard_1.ChartHoverCard, { XValue: calloutProps === null || calloutProps === void 0 ? void 0 : calloutProps.XValue, YValue: calloutProps === null || calloutProps === void 0 ? void 0 : calloutProps.YValue, color: calloutProps === null || calloutProps === void 0 ? void 0 : calloutProps.color }))))),
        _renderLegends())) : (React.createElement("div", { id: _emptyChartId, role: 'alert', style: { opacity: '0' }, "aria-label": 'Graph has no data to display' }));
});
exports.FunnelChartBase.displayName = 'FunnelChart';
// eslint-disable-next-line @typescript-eslint/no-deprecated
exports.FunnelChartBase.defaultProps = {
    orientation: 'horizontal',
};
//# sourceMappingURL=FunnelChart.base.js.map