import { __rest } from "tslib";
import * as React from 'react';
import PopoverBase from '../../helpers/PopoverBase/PopoverBase';
import { KEY_CODES } from '../../helpers/constants';
import styles from '@patternfly/react-styles/css/components/Popover/popover';
import '@patternfly/react-styles/css/components/Tooltip/tippy.css';
import '@patternfly/react-styles/css/components/Tooltip/tippy-overrides.css';
import { css } from '@patternfly/react-styles';
import { PopoverContent } from './PopoverContent';
import { PopoverBody } from './PopoverBody';
import { PopoverHeader } from './PopoverHeader';
import { PopoverFooter } from './PopoverFooter';
import { PopoverCloseButton } from './PopoverCloseButton';
import { GenerateId } from '../../helpers/GenerateId/GenerateId';
import popoverMaxWidth from '@patternfly/react-tokens/dist/js/c_popover_MaxWidth';
import { FocusTrap } from '../../helpers';
export var PopoverPosition;
(function (PopoverPosition) {
    PopoverPosition["auto"] = "auto";
    PopoverPosition["top"] = "top";
    PopoverPosition["bottom"] = "bottom";
    PopoverPosition["left"] = "left";
    PopoverPosition["right"] = "right";
})(PopoverPosition || (PopoverPosition = {}));
export class Popover extends React.Component {
    constructor(props) {
        super(props);
        this.hideOrNotify = () => {
            if (this.props.isVisible === null) {
                // Handle closing
                this.tip.hide();
            }
            else {
                // notify consumer
                this.props.shouldClose(this.tip);
            }
        };
        this.handleEscOrEnterKey = (event) => {
            if (event.keyCode === KEY_CODES.ESCAPE_KEY && this.tip.state.isVisible) {
                this.hideOrNotify();
            }
            else if (!this.state.isOpen && event.keyCode === KEY_CODES.ENTER) {
                this.setState({ focusTrapActive: true });
            }
        };
        this.storeTippyInstance = (tip) => {
            if (this.props.minWidth) {
                tip.popperChildren.tooltip.style.minWidth = this.props.minWidth;
            }
            tip.popperChildren.tooltip.classList.add(styles.popover);
            this.tip = tip;
        };
        this.closePopover = () => {
            this.hideOrNotify();
            this.setState({ focusTrapActive: false });
        };
        this.hideAllPopovers = () => {
            document.querySelectorAll('.tippy-popper').forEach((popper) => {
                if (popper._tippy) {
                    popper._tippy.hide();
                }
            });
        };
        this.onHide = (tip) => {
            if (this.state.isOpen) {
                this.setState({ isOpen: false });
            }
            return this.props.onHide(tip);
        };
        this.onHidden = (tip) => this.props.onHidden(tip);
        this.onMount = (tip) => this.props.onMount(tip);
        this.onShow = (tip) => {
            const { hideOnOutsideClick, isVisible, onShow } = this.props;
            // hide all other open popovers first if events are managed by us
            if (!hideOnOutsideClick && isVisible === null) {
                this.hideAllPopovers();
            }
            if (this.state.isOpen === false) {
                this.setState({ isOpen: true });
            }
            return onShow(tip);
        };
        this.onShown = (tip) => this.props.onShown(tip);
        this.onContentMouseDown = () => {
            if (this.state.focusTrapActive) {
                this.setState({ focusTrapActive: false });
            }
        };
        this.state = {
            isOpen: false,
            focusTrapActive: false
        };
    }
    componentDidMount() {
        document.addEventListener('keydown', this.handleEscOrEnterKey, false);
    }
    componentWillUnmount() {
        document.removeEventListener('keydown', this.handleEscOrEnterKey, false);
    }
    render() {
        /* eslint-disable @typescript-eslint/no-unused-vars */
        const _a = this.props, { position, enableFlip, children, className, 'aria-label': ariaLabel, headerContent, bodyContent, footerContent, isVisible, shouldClose, appendTo, hideOnOutsideClick, onHide, onHidden, onShow, onShown, onMount, zIndex, minWidth, maxWidth, closeBtnAriaLabel, distance, boundary, flipBehavior, tippyProps } = _a, rest = __rest(_a, ["position", "enableFlip", "children", "className", 'aria-label', "headerContent", "bodyContent", "footerContent", "isVisible", "shouldClose", "appendTo", "hideOnOutsideClick", "onHide", "onHidden", "onShow", "onShown", "onMount", "zIndex", "minWidth", "maxWidth", "closeBtnAriaLabel", "distance", "boundary", "flipBehavior", "tippyProps"]);
        /* eslint-enable @typescript-eslint/no-unused-vars */
        if (!headerContent && !ariaLabel) {
            return new Error('aria-label is required when header is not used');
        }
        const content = this.state.isOpen ? (React.createElement(GenerateId, null, randomId => (React.createElement(FocusTrap, { active: this.state.focusTrapActive, focusTrapOptions: { clickOutsideDeactivates: true } },
            React.createElement("div", Object.assign({ className: css(!enableFlip &&
                    (styles.modifiers[position] || styles.modifiers.top), className), role: "dialog", "aria-modal": "true", "aria-label": headerContent ? undefined : ariaLabel, "aria-labelledby": headerContent ? `popover-${randomId}-header` : undefined, "aria-describedby": `popover-${randomId}-body`, onMouseDown: this.onContentMouseDown }, rest),
                React.createElement(PopoverContent, null,
                    React.createElement(PopoverCloseButton, { onClose: this.closePopover, "aria-label": closeBtnAriaLabel }),
                    headerContent && React.createElement(PopoverHeader, { id: `popover-${randomId}-header` }, headerContent),
                    React.createElement(PopoverBody, { id: `popover-${randomId}-body` }, bodyContent),
                    footerContent && React.createElement(PopoverFooter, null, footerContent))))))) : (React.createElement(React.Fragment, null));
        const handleEvents = isVisible === null;
        const shouldHideOnClick = () => {
            if (handleEvents) {
                if (hideOnOutsideClick === true) {
                    return true;
                }
                return 'toggle';
            }
            return false;
        };
        return (React.createElement(PopoverBase, Object.assign({}, tippyProps, { arrow: true, onCreate: this.storeTippyInstance, maxWidth: maxWidth, zIndex: zIndex, appendTo: appendTo, content: content, lazy: true, trigger: handleEvents ? 'click' : 'manual', isVisible: isVisible, hideOnClick: shouldHideOnClick(), theme: "pf-popover", interactive: true, interactiveBorder: 0, placement: position, distance: distance, flip: enableFlip, flipBehavior: flipBehavior, boundary: boundary, popperOptions: {
                modifiers: {
                    preventOverflow: {
                        enabled: enableFlip
                    },
                    hide: {
                        enabled: enableFlip
                    }
                }
            }, onHide: (tip) => this.onHide(tip), onHidden: (tip) => this.onHidden(tip), onShow: (tip) => this.onShow(tip), onShown: (tip) => this.onShown(tip), onMount: (tip) => this.onMount(tip) }), children));
    }
}
Popover.defaultProps = {
    position: 'top',
    enableFlip: true,
    className: '',
    isVisible: null,
    shouldClose: () => null,
    'aria-label': '',
    headerContent: null,
    footerContent: null,
    appendTo: () => document.body,
    hideOnOutsideClick: true,
    onHide: () => null,
    onHidden: () => null,
    onShow: () => null,
    onShown: () => null,
    onMount: () => null,
    zIndex: 9999,
    maxWidth: popoverMaxWidth && popoverMaxWidth.value,
    closeBtnAriaLabel: 'Close',
    distance: 25,
    boundary: 'window',
    // For every initial starting position, there are 3 escape positions
    flipBehavior: ['top', 'right', 'bottom', 'left', 'top', 'right', 'bottom'],
    tippyProps: {}
};
//# sourceMappingURL=Popover.js.map