import { __assign, __extends, __spreadArray } from "tslib";
import * as React from 'react';
import { HoverCard, HoverCardType } from '@fluentui/react/lib/HoverCard';
import { classNamesFunction, find, getNativeProps, buttonProperties } from '@fluentui/react/lib/Utilities';
import { ResizeGroup } from '@fluentui/react/lib/ResizeGroup';
import { OverflowSet } from '@fluentui/react/lib/OverflowSet';
import { FocusZone, FocusZoneDirection, FocusZoneTabbableElements } from '@fluentui/react-focus';
import { Shape } from './shape';
import { cloneLegendsToSVG } from '../../utilities/image-export-utils';
var getClassNames = classNamesFunction();
var LegendsBase = /** @class */ (function (_super) {
    __extends(LegendsBase, _super);
    function LegendsBase(props) {
        var _a;
        var _b, _c, _d;
        var _this = _super.call(this, props) || this;
        /** Boolean variable to check if one or more legends are selected */
        _this._isLegendSelected = false;
        _this.toSVG = function (svgWidth, isRTL) {
            if (isRTL === void 0) { isRTL = false; }
            return cloneLegendsToSVG(_this.props.legends, svgWidth, {
                selectedLegends: _this.state.selectedLegends,
                centerLegends: !!_this.props.centerLegends,
                textClassName: _this._classNames.text,
                isRTL: isRTL,
            }, _this._rootElem);
        };
        _this._onRenderData = function (data) {
            var _a = _this.props, overflowProps = _a.overflowProps, _b = _a.allowFocusOnLegends, allowFocusOnLegends = _b === void 0 ? true : _b, _c = _a.canSelectMultipleLegends, canSelectMultipleLegends = _c === void 0 ? false : _c;
            var rootStyles = {
                root: {
                    justifyContent: _this.props.centerLegends ? 'center' : 'unset',
                    flexWrap: 'wrap',
                },
            };
            return (React.createElement(FocusZone, __assign({}, (allowFocusOnLegends && {
                role: 'listbox',
                'aria-label': 'Legends',
                'aria-multiselectable': canSelectMultipleLegends,
            })),
                React.createElement(OverflowSet, __assign({ items: data.primary, overflowItems: data.overflow, onRenderItem: _this._renderButton, onRenderOverflowButton: _this._renderOverflowItems }, overflowProps, { styles: __assign(__assign({}, rootStyles), overflowProps === null || overflowProps === void 0 ? void 0 : overflowProps.styles) }))));
        };
        _this._onReduceData = function (currentdata) {
            if (currentdata.primary.length === 0) {
                return;
            }
            var overflow = __spreadArray(__spreadArray([], currentdata.primary.slice(-1), true), currentdata.overflow, true);
            var primary = currentdata.primary.slice(0, -1);
            return { primary: primary, overflow: overflow };
        };
        _this._onGrowData = function (currentdata) {
            if (currentdata.overflow.length === 0) {
                return;
            }
            var overflow = currentdata.overflow.slice(1);
            var primary = __spreadArray(__spreadArray([], currentdata.primary, true), currentdata.overflow.slice(0, 1), true);
            return { primary: primary, overflow: overflow };
        };
        /**
         * Get the new selected legends based on the legend that was clicked when multi-select is enabled.
         * @param legend The legend that was clicked
         * @returns An object with the new selected legend(s) state data.
         */
        _this._getNewSelectedLegendsForMultiselect = function (legend) {
            var selectedLegends = __assign({}, _this.state.selectedLegends);
            if (selectedLegends[legend.title]) {
                // Delete entry for the deselected legend to make
                // the number of keys equal to the number of selected legends
                delete selectedLegends[legend.title];
            }
            else {
                selectedLegends[legend.title] = true;
                // Clear set if all legends are selected
                if (Object.keys(selectedLegends).length === _this.props.legends.length) {
                    selectedLegends = {};
                }
            }
            return selectedLegends;
        };
        /**
         * Get the new selected legends based on the legend that was clicked when single-select is enabled.
         * @param legend The legend that was clicked
         * @returns An object with the new selected legend state data.
         */
        _this._getNewSelectedLegendsForSingleSelect = function (legend) {
            var _a;
            return _this.state.selectedLegends[legend.title] ? {} : (_a = {}, _a[legend.title] = true, _a);
        };
        _this._onClick = function (legend, event) {
            var _a, _b, _c;
            var _d = _this.props.canSelectMultipleLegends, canSelectMultipleLegends = _d === void 0 ? false : _d;
            var nextSelectedLegends = canSelectMultipleLegends
                ? _this._getNewSelectedLegendsForMultiselect(legend)
                : _this._getNewSelectedLegendsForSingleSelect(legend);
            _this.setState({ selectedLegends: nextSelectedLegends });
            (_b = (_a = _this.props).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, Object.keys(nextSelectedLegends), event, legend);
            (_c = legend.action) === null || _c === void 0 ? void 0 : _c.call(legend);
        };
        _this._onRenderCompactCard = function (expandingCard) {
            var _a = _this.props, _b = _a.allowFocusOnLegends, allowFocusOnLegends = _b === void 0 ? true : _b, className = _a.className, styles = _a.styles, theme = _a.theme, _c = _a.canSelectMultipleLegends, canSelectMultipleLegends = _c === void 0 ? false : _c;
            var overflowHoverCardLegends = [];
            var classNames = getClassNames(styles, {
                theme: theme,
                className: className,
            });
            expandingCard.renderData.forEach(function (legend, index) {
                var hoverCardElement = _this._renderButton(legend, index, true);
                overflowHoverCardLegends.push(hoverCardElement);
            });
            var hoverCardData = (React.createElement(FocusZone, __assign({}, (allowFocusOnLegends && {
                role: 'listbox',
                'aria-label': 'Legends',
                'aria-multiselectable': canSelectMultipleLegends,
            }), { direction: FocusZoneDirection.vertical, handleTabKey: FocusZoneTabbableElements.all, isCircularNavigation: true }, _this.props.focusZonePropsInHoverCard, { className: classNames.hoverCardRoot }), overflowHoverCardLegends));
            return hoverCardData;
        };
        _this._renderOverflowItems = function (legends) {
            var _a = _this.props.allowFocusOnLegends, allowFocusOnLegends = _a === void 0 ? true : _a;
            var items = [];
            legends.forEach(function (legend, i) {
                items.push({ key: i.toString(), name: legend.title, onClick: legend.action });
            });
            var renderOverflowData = { renderData: legends };
            var _b = _this.props, theme = _b.theme, className = _b.className, styles = _b.styles, overflowText = _b.overflowText;
            var classNames = getClassNames(styles, {
                theme: theme,
                className: className,
            });
            var plainCardProps = {
                onRenderPlainCard: _this._onRenderCompactCard,
                renderData: renderOverflowData,
            };
            var overflowString = overflowText ? overflowText : 'more';
            // execute similar to "_onClick" and "_onLeave" logic at HoverCard onCardHide event
            var onHoverCardHideHandler = function () {
                _this.setState({ isHoverCardVisible: false });
                // Unhighlight the focused legend in the hover card
                var activeOverflowItem = find(legends, function (legend) { return legend.title === _this.state.activeLegend; });
                if (activeOverflowItem) {
                    _this.setState({ activeLegend: '' });
                    if (activeOverflowItem.onMouseOutAction) {
                        activeOverflowItem.onMouseOutAction();
                    }
                }
            };
            return (React.createElement(HoverCard, { type: HoverCardType.plain, plainCardProps: plainCardProps, instantOpenOnClick: true, 
                // eslint-disable-next-line react/jsx-no-bind
                onCardHide: onHoverCardHideHandler, setInitialFocus: true, trapFocus: true, onCardVisible: _this._hoverCardVisible, styles: classNames.subComponentStyles.hoverCardStyles, cardDismissDelay: 300, target: _this._hoverCardRef },
                React.createElement("div", { role: "option" },
                    React.createElement("div", __assign({ className: classNames.overflowIndicationTextStyle, ref: function (rootElem) { return (_this._hoverCardRef = rootElem); } }, (allowFocusOnLegends && {
                        role: 'button',
                        'aria-expanded': _this.state.isHoverCardVisible,
                        'aria-label': "".concat(items.length, " ").concat(overflowString),
                    }), { "data-is-focusable": allowFocusOnLegends }),
                        items.length,
                        " ",
                        overflowString))));
        };
        _this._hoverCardVisible = function () {
            _this.setState({ isHoverCardVisible: true });
        };
        _this._onHoverOverLegend = function (legend) {
            if (legend.hoverAction) {
                _this.setState({ activeLegend: legend.title });
                legend.hoverAction();
            }
        };
        _this._onLeave = function (legend) {
            if (legend.onMouseOutAction) {
                _this.setState({ activeLegend: '' });
                legend.onMouseOutAction();
            }
        };
        _this._renderButton = function (data, index, overflow) {
            var _a = _this.props.allowFocusOnLegends, allowFocusOnLegends = _a === void 0 ? true : _a;
            var legend = {
                title: data.title,
                color: data.color,
                shape: data.shape,
                action: data.action,
                hoverAction: data.hoverAction,
                onMouseOutAction: data.onMouseOutAction,
                stripePattern: data.stripePattern,
                isLineLegendInBarChart: data.isLineLegendInBarChart,
                opacity: data.opacity,
            };
            var color = _this._getColor(legend.title, legend.color);
            var _b = _this.props, theme = _b.theme, className = _b.className, styles = _b.styles;
            var classNames = getClassNames(styles, {
                theme: theme,
                className: className,
                colorOnSelectedState: color,
                borderColor: legend.color,
                overflow: overflow,
                stripePattern: legend.stripePattern,
                isLineLegendInBarChart: legend.isLineLegendInBarChart,
                opacity: legend.opacity,
            });
            var onClickHandler = function (event) {
                _this._onClick(legend, event);
            };
            var onHoverHandler = function () {
                _this._onHoverOverLegend(legend);
            };
            var onMouseOut = function () {
                _this._onLeave(legend);
            };
            var shape = _this._getShape(classNames, legend, color);
            return (React.createElement("button", __assign({}, (allowFocusOnLegends && {
                'aria-selected': !!_this.state.selectedLegends[legend.title],
                role: 'option',
                'aria-label': "".concat(legend.title),
                'aria-setsize': data['aria-setsize'],
                'aria-posinset': data['aria-posinset'],
            }), (data.nativeButtonProps && __assign({}, data.nativeButtonProps)), { key: index, className: classNames.legend, onClick: onClickHandler, onMouseOver: onHoverHandler, onMouseOut: onMouseOut, onFocus: onHoverHandler, onBlur: onMouseOut, "data-is-focusable": allowFocusOnLegends }),
                shape,
                React.createElement("div", { className: classNames.text }, legend.title)));
        };
        //let defaultSelectedLegends = {};
        var initialSelectedLegends = (_b = props.selectedLegends) !== null && _b !== void 0 ? _b : props.defaultSelectedLegends;
        var initialSelectedLegend = (_c = props.selectedLegend) !== null && _c !== void 0 ? _c : props.defaultSelectedLegend;
        var selectedLegendsState = {};
        if (props.canSelectMultipleLegends) {
            selectedLegendsState =
                ((_d = (initialSelectedLegends !== null && initialSelectedLegends !== void 0 ? initialSelectedLegends : [])) === null || _d === void 0 ? void 0 : _d.reduce(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                function (combineDict, key) {
                    var _a;
                    return (__assign((_a = {}, _a[key] = true, _a), combineDict));
                }, {})) || {};
        }
        else if (initialSelectedLegend) {
            selectedLegendsState = (_a = {}, _a[initialSelectedLegend] = true, _a);
        }
        _this.state = {
            activeLegend: '',
            isHoverCardVisible: false,
            selectedLegends: selectedLegendsState,
        };
        return _this;
    }
    LegendsBase.getDerivedStateFromProps = function (newProps, prevState) {
        var _a;
        var selectedLegend = newProps.selectedLegend, selectedLegends = newProps.selectedLegends;
        if (newProps.canSelectMultipleLegends && selectedLegends !== undefined) {
            return __assign(__assign({}, prevState), { selectedLegends: selectedLegends.reduce(
                // eslint-disable-next-line @typescript-eslint/no-explicit-any
                function (combinedDict, key) {
                    var _a;
                    return (__assign((_a = {}, _a[key] = true, _a), combinedDict));
                }, {}) });
        }
        if (!newProps.canSelectMultipleLegends && selectedLegend !== undefined) {
            return __assign(__assign({}, prevState), { selectedLegends: (_a = {}, _a[selectedLegend] = true, _a) });
        }
        return prevState;
    };
    LegendsBase.prototype.render = function () {
        var _this = this;
        var _a = this.props, theme = _a.theme, className = _a.className, styles = _a.styles;
        this._classNames = getClassNames(styles, {
            theme: theme,
            className: className,
        });
        this._isLegendSelected = Object.keys(this.state.selectedLegends).length > 0;
        var dataToRender = this._generateData();
        return (React.createElement("div", { className: this._classNames.root, ref: function (el) { return (_this._rootElem = el); } }, this.props.enabledWrapLines ? (this._onRenderData(dataToRender)) : (React.createElement(ResizeGroup, { data: dataToRender, onReduceData: this._onReduceData, onRenderData: this._onRenderData, onGrowData: this._onGrowData }))));
    };
    LegendsBase.prototype._generateData = function () {
        var _this = this;
        var _a = this.props, _b = _a.allowFocusOnLegends, allowFocusOnLegends = _b === void 0 ? true : _b, shape = _a.shape;
        var dataItems = this.props.legends.map(function (legend, index) {
            return __assign(__assign({}, (allowFocusOnLegends && {
                nativeButtonProps: getNativeProps(legend, buttonProperties, [
                    'title',
                ]),
                'aria-setsize': _this.props.legends.length,
                'aria-posinset': index + 1,
            })), { title: legend.title, action: legend.action, hoverAction: legend.hoverAction, onMouseOutAction: legend.onMouseOutAction, color: legend.color, shape: shape ? shape : legend.shape, stripePattern: legend.stripePattern, isLineLegendInBarChart: legend.isLineLegendInBarChart, opacity: legend.opacity, key: index });
        });
        var result = {
            primary: dataItems,
            overflow: [],
        };
        return result;
    };
    LegendsBase.prototype._getShape = function (classNames, legend, color) {
        var svgParentProps = {
            className: classNames.shape,
        };
        var svgChildProps = {
            fill: color,
            strokeWidth: 2,
            stroke: legend.color,
        };
        return (React.createElement(Shape, { svgProps: svgParentProps, pathProps: svgChildProps, shape: legend.shape, classNameForNonSvg: classNames.rect }));
    };
    LegendsBase.prototype._getColor = function (title, color) {
        var theme = this.props.theme;
        var legendColor = color;
        // if one or more legends are selected
        if (this._isLegendSelected) {
            // if the given legend (title) is one of the selected legends
            if (this.state.selectedLegends[title]) {
                legendColor = color;
            }
            // if the given legend is unselected
            else {
                legendColor = theme.semanticColors.buttonBackground;
            }
        }
        // if no legend is selected
        else {
            // if the given legend is hovered
            // or none of the legends is hovered
            if (this.state.activeLegend === title || this.state.activeLegend === '') {
                legendColor = color;
            }
            // if there is a hovered legend but the given legend is not the one
            else {
                legendColor = theme.semanticColors.buttonBackground;
            }
        }
        return legendColor;
    };
    return LegendsBase;
}(React.Component));
export { LegendsBase };
//# sourceMappingURL=Legends.base.js.map