/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Item
 */
import "./PopupButton.scss";
import classnames from "classnames";
import * as React from "react";
import { ConditionalBooleanValue, SpecialKey } from "@itwin/appui-abstract";
import { BadgeUtilities, Icon, withOnOutsideClick } from "@itwin/core-react";
import { ExpandableItem, Item } from "@itwin/appui-layout-react";
import { SyncUiEventDispatcher } from "../syncui/SyncUiEventDispatcher";
import { UiFramework } from "../UiFramework";
import { PropsHelper } from "../utils/PropsHelper";
import { ToolbarDragInteractionContext } from "./DragInteraction";
import { InternalFrontstageManager } from "../frontstage/InternalFrontstageManager";
/* eslint-disable deprecation/deprecation */
// cSpell:ignore popupbutton
// eslint-disable-next-line @typescript-eslint/naming-convention
const DivWithOnOutsideClick = withOnOutsideClick((props) => (React.createElement("div", { ...props })), undefined, true);
const isFunction = (node) => {
    if (typeof node === "function")
        return true;
    return false;
};
/**
 * Used to provide custom popup button in toolbar.
 * @public
 * @deprecated in 2.x. Use PopupItem in ToolbarWithOverflow or popupPanelNode in CustomItemDef
 */
export class PopupButton extends React.Component {
    constructor(props) {
        super(props);
        this._label = "";
        this._componentUnmounting = false;
        this._closeOnPanelOpened = true;
        this._ref = React.createRef();
        this._isMounted = false;
        /** Minimizes the expandable component. */
        this.minimize = () => {
            if (this._isMounted)
                this.setState({
                    isPressed: false,
                });
        };
        this._handleSyncUiEvent = (args) => {
            // istanbul ignore if
            if (this._componentUnmounting)
                return;
            let refreshState = false;
            let newState = { ...this.state };
            // istanbul ignore else
            if (this.props.stateSyncIds && this.props.stateSyncIds.length > 0) // eslint-disable-line deprecation/deprecation
                refreshState = this.props.stateSyncIds.some((value) => args.eventIds.has(value.toLowerCase())); // eslint-disable-line deprecation/deprecation
            // istanbul ignore else
            if (refreshState) {
                // istanbul ignore else
                if (this.props.stateFunc) // eslint-disable-line deprecation/deprecation
                    newState = this.props.stateFunc(newState); // eslint-disable-line deprecation/deprecation
                // istanbul ignore next
                if ((this.state.isActive !== newState.isActive) || (this.state.isEnabled !== newState.isEnabled) || (this.state.isVisible !== newState.isVisible)) {
                    if (this._isMounted)
                        this.setState({ isActive: newState.isActive, isEnabled: newState.isEnabled, isVisible: newState.isVisible });
                }
            }
        };
        this._handleToolPanelOpenedEvent = () => {
            if (!this._closeOnPanelOpened)
                return;
            this.minimize();
        };
        this._handleKeyDown = (e) => {
            // istanbul ignore next
            if (e.key === SpecialKey.Escape) {
                this.minimize();
                UiFramework.keyboardShortcuts.setFocusToHome();
            }
        };
        this._handleClick = () => {
            // istanbul ignore else
            if (this._isMounted)
                this.setState((prevState) => {
                    const isPressed = !prevState.isPressed;
                    return {
                        isPressed,
                    };
                }, () => {
                    const expand = !!this.state.isPressed;
                    this._closeOnPanelOpened = false;
                    expand && InternalFrontstageManager.onToolPanelOpenedEvent.emit();
                    this._closeOnPanelOpened = true;
                    this.props.onExpanded && this.props.onExpanded(expand);
                });
        };
        this._handleOutsideClick = (e) => {
            this._ref.current && (e.target instanceof Node) && !this._ref.current.contains(e.target) && this.minimize();
        };
        if (props.label)
            this._label = props.label;
        // istanbul ignore else
        else if (props.labelKey)
            this._label = UiFramework.localization.getLocalizedString(props.labelKey);
        this.state = {
            isVisible: undefined !== props.isVisible ? props.isVisible : true,
            isEnabled: undefined !== props.isEnabled ? props.isEnabled : true,
            isActive: undefined !== props.isActive ? props.isActive : false,
            isPressed: undefined !== props.isPressed ? props.isPressed : false,
        };
    }
    get label() {
        return PropsHelper.getStringFromSpec(this._label);
    }
    componentDidMount() {
        this._isMounted = true;
        SyncUiEventDispatcher.onSyncUiEvent.addListener(this._handleSyncUiEvent);
        InternalFrontstageManager.onToolPanelOpenedEvent.addListener(this._handleToolPanelOpenedEvent);
    }
    componentWillUnmount() {
        this._isMounted = false;
        this._componentUnmounting = true;
        SyncUiEventDispatcher.onSyncUiEvent.removeListener(this._handleSyncUiEvent);
        InternalFrontstageManager.onToolPanelOpenedEvent.addListener(this._handleToolPanelOpenedEvent);
    }
    /** Renders PopupButton */
    render() {
        if (!this.state.isVisible)
            return null;
        const icon = React.createElement(Icon, { iconSpec: this.props.iconSpec });
        const badge = BadgeUtilities.getComponentForBadgeType(this.props.badgeType);
        const { isDisabled, ...otherProps } = this.props;
        return (React.createElement(ToolbarDragInteractionContext.Consumer, null, (isDragEnabled) => {
            return (React.createElement(ExpandableItem, { ...otherProps, isDisabled: ConditionalBooleanValue.getValue(isDisabled), hideIndicator: isDragEnabled, panel: this.getExpandedContent() },
                React.createElement("div", { ref: this._ref },
                    React.createElement(Item, { badge: badge, icon: icon, onKeyDown: this._handleKeyDown, onClick: this._handleClick, onSizeKnown: this.props.onSizeKnown, title: this.label }))));
        }));
    }
    /** Returns expanded content panel */
    getExpandedContent() {
        if (!this.state.isPressed)
            return undefined;
        const classNames = classnames("nz-toolbar-item-expandable-group-panel", this.props.noPadding && "uifw-popupbutton-noPadding");
        return (React.createElement(DivWithOnOutsideClick, { className: classNames, onOutsideClick: this._handleOutsideClick }, isFunction(this.props.children) ? this.props.children({
            closePanel: this.minimize,
        }) : this.props.children));
    }
}
//# sourceMappingURL=PopupButton.js.map