import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { SoftListGroup, SoftListGroupItem } from '../ListGroup';
import { SoftNavDrawerFlyout } from './SoftNavDrawerFlyout';
import { SoftOutsideClickDetector } from '../OutsideClickDetector';
import { SoftI18n } from '../i18n';
import { SoftFlexItem } from '../flex';
export class SoftNavDrawer extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isCollapsed: true,
            flyoutIsCollapsed: true,
            outsideClickDisabled: true,
            isManagingFocus: false,
            toolTipsEnabled: true,
            navFlyoutTitle: '',
            navFlyoutContent: '',
        };
        this.toggleOpen = () => {
            this.setState({
                isCollapsed: !this.state.isCollapsed
            });
            setTimeout(() => {
                this.setState({
                    outsideClickDisabled: this.state.isCollapsed,
                    toolTipsEnabled: this.state.isCollapsed,
                });
            }, 150);
        };
        this.expandDrawer = () => {
            this.setState({
                isCollapsed: false,
                outsideClickDisabled: false,
            });
            setTimeout(() => {
                this.setState({
                    toolTipsEnabled: false,
                });
            }, 150);
        };
        this.collapseDrawer = () => {
            this.setState({
                isCollapsed: true,
                outsideClickDisabled: this.state.flyoutIsCollapsed,
                toolTipsEnabled: true,
            });
            // Scrolls the menu and flyout back to top when the nav drawer collapses
            setTimeout(() => {
                document.getElementById('navDrawerMenu').scrollTop = 0;
            }, 50);
        };
        this.manageFocus = () => {
            // This prevents the drawer from collapsing when tabbing through children
            // by clearing the timeout thus cancelling the onBlur event (see focusOut).
            // This means isManagingFocus remains true as long as a child element
            // has focus. This is the case since React bubbles up onFocus and onBlur
            // events from the child elements.
            clearTimeout(this.timeoutID);
            if (!this.state.isManagingFocus) {
                this.setState({
                    isManagingFocus: true,
                });
            }
        };
        this.focusOut = () => {
            // This collapses the drawer when no children have focus (i.e. tabbed out).
            // In other words, if focus does not bubble up from a child element, then
            // the drawer will collapse. See the corresponding block in expandDrawer
            // (called by onFocus) which cancels this operation via clearTimeout.
            this.timeoutID = setTimeout(() => {
                if (this.state.isManagingFocus) {
                    this.setState({
                        isManagingFocus: false,
                    });
                    this.closeBoth();
                }
            }, 0);
        };
        this.expandFlyout = (links, title) => {
            const content = links;
            if (this.state.navFlyoutTitle === title) {
                this.collapseFlyout();
            }
            else {
                this.setState({
                    flyoutIsCollapsed: false,
                    navFlyoutTitle: title,
                    navFlyoutContent: content,
                    isCollapsed: true,
                    toolTipsEnabled: false,
                    outsideClickDisabled: false,
                });
            }
        };
        this.collapseFlyout = () => {
            this.setState({
                flyoutIsCollapsed: true,
                navFlyoutTitle: null,
                navFlyoutContent: null,
                toolTipsEnabled: true,
            });
        };
        this.closeBoth = () => {
            this.collapseDrawer();
            this.collapseFlyout();
        };
        this.handleDrawerMenuClick = e => {
            // walk up e.target until either:
            // 1. a[href] - close the menu
            // 2. document.body - do nothing
            let element = e.target;
            while (element !== undefined && element !== document.body && (element.tagName !== 'A' || element.getAttribute('href') === undefined)) {
                element = element.parentElement;
            }
            if (element !== document.body) {
                // this is an anchor with an href
                this.closeBoth();
            }
        };
    }
    render() {
        const { children, className, showExpandButton, showToolTips, ...rest } = this.props;
        const classes = classNames('softNavDrawer', {
            'softNavDrawer-isCollapsed': this.state.isCollapsed,
            'softNavDrawer-isExpanded': !this.state.isCollapsed,
            'softNavDrawer-flyoutIsCollapsed': this.state.flyoutIsCollapsed,
            'softNavDrawer-flyoutIsExpanded': !this.state.flyoutIsCollapsed,
        }, className);
        let footerContent;
        if (showExpandButton) {
            footerContent = (React.createElement(SoftListGroup, { className: "softNavDrawer__expandButton", flush: true },
                React.createElement(SoftI18n, { tokens: ['softNavDrawer.sideNavCollapse', 'softNavDrawer.sideNavExpand'], defaults: ['Collapse', 'Expand'] }, ([sideNavCollapse, sideNavExpand]) => (React.createElement(SoftListGroupItem, { label: this.state.isCollapsed ? sideNavExpand : sideNavCollapse, iconType: this.state.isCollapsed ? 'menuRight' : 'menuLeft', size: "s", showToolTip: this.state.isCollapsed, onClick: this.state.isCollapsed ? () => {
                        this.expandDrawer();
                        this.collapseFlyout();
                    } : () => this.collapseDrawer(), "data-test-subj": this.state.isCollapsed ? 'navDrawerExpandButton-isCollapsed' : 'navDrawerExpandButton-isExpanded' })))));
        }
        const flyoutContent = (React.createElement(SoftNavDrawerFlyout, { id: "navDrawerFlyout", title: this.state.navFlyoutTitle, isCollapsed: this.state.flyoutIsCollapsed, listItems: this.state.navFlyoutContent, wrapText: true }));
        // Add an onClick that expands the flyout sub menu for any list items (links)
        // that have a flyoutMenu prop (sub links)
        let modifiedChildren = children;
        // 1. Loop through the SoftNavDrawer children (SoftListGroup, SoftHorizontalRules, etc)
        modifiedChildren = React.Children.map(this.props.children, child => {
            // 2. Check if child is an SoftNavDrawerGroup and if it does have a flyout, add the expand function
            // @ts-ignore
            if (child.type.name === 'SoftNavDrawerGroup') {
                // @ts-ignore
                const item = React.cloneElement(child, {
                    flyoutMenuButtonClick: this.expandFlyout,
                    showToolTips: this.state.toolTipsEnabled && showToolTips,
                });
                return item;
            }
            else {
                return child;
            }
        });
        const menuClasses = classNames('softNavDrawerMenu', { 'softNavDrawerMenu-hasFooter': footerContent, });
        return (React.createElement(SoftOutsideClickDetector, { onOutsideClick: () => this.closeBoth(), isDisabled: this.state.outsideClickDisabled },
            React.createElement("div", Object.assign({ className: classes, onBlur: this.focusOut, onFocus: this.manageFocus }, rest),
                React.createElement(SoftFlexItem, { grow: false },
                    React.createElement("div", { id: "navDrawerMenu", className: menuClasses, onClick: this.handleDrawerMenuClick },
                        footerContent,
                        modifiedChildren)),
                flyoutContent)));
    }
}
SoftNavDrawer.propTypes = {
    children: PropTypes.node,
    className: PropTypes.string,
    /**
     * Adds fixed toggle button to bottom of menu area
     */
    showExpandButton: PropTypes.bool,
    /**
     * Display tooltips on side nav items
     */
    showToolTips: PropTypes.bool,
};
SoftNavDrawer.defaultProps = {
    showExpandButton: true,
    showToolTips: true,
};
//# sourceMappingURL=SoftNavDrawer.js.map