'use strict';
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
            t[p[i]] = s[p[i]];
    return t;
};
import React, { Children, cloneElement } from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { isEmpty, includes } from 'lodash';
import Nav from 'react-bootstrap/lib/Nav';
import { KeyCodes } from '../../utils/constants';
import { NavDropdown, TabItem } from '..';
import { cleanEmptyChildren, isElementHasType } from '../utils/functions';
// export const tabPanelStyle: TabPanelStyle;
export var TAB_PANEL_STYLES = {
    TABS: 'tabs',
    PILLS: 'pills',
    MENU: 'menu'
};
export var TAB_PANEL_ITEM_ROLES = {
    menuitem: 'menuitem',
    tab: 'tab'
};
var TabPanel = /** @class */ (function (_super) {
    __extends(TabPanel, _super);
    function TabPanel() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.state = {
            focusedItemIndex: 0,
            isAnyDropdownOpen: false,
            isDropdownOpen: false,
            dropdownOpenStatuses: {},
            panelTabIndex: 0 // init with 0 to be able to get focus from another elements
        };
        _this.isStyledAsTab = function () {
            var _a = _this.props, bsStyle = _a.bsStyle, activeKey = _a.activeKey;
            return bsStyle === TAB_PANEL_STYLES.TABS || (activeKey || activeKey === 0);
        };
        _this.setFocusedItemByIndex = function (index) {
            var rawChildren = _this.props.children;
            var children = cleanEmptyChildren(rawChildren);
            if (index !== -1 && !children[index].props.disabled) {
                _this.setState({
                    focusedItemIndex: index
                });
            }
        };
        _this.handleClick = function (event) {
            var tabPanelNode = ReactDOM.findDOMNode(_this);
            var childNode = event.target.parentNode;
            var index = TabPanel.getChildIndex(tabPanelNode, childNode);
            _this.setFocusedItemByIndex(index);
        };
        _this.handleKeyDown = function (event) {
            var rawChildren = _this.props.children;
            var children = cleanEmptyChildren(rawChildren);
            var _a = _this.state, focusedItemIndex = _a.focusedItemIndex, isAnyDropdownOpen = _a.isAnyDropdownOpen;
            var focusedTab = children[focusedItemIndex];
            switch (event.keyCode) {
                case KeyCodes.ARROW_LEFT:
                case KeyCodes.ARROW_UP:
                    if (!isAnyDropdownOpen) {
                        var previousTab = _this.getPreviousTab();
                        _this.setFocusedItemByIndex(previousTab);
                    }
                    break;
                case KeyCodes.ARROW_RIGHT:
                    if (!isAnyDropdownOpen) {
                        var nextTab = _this.getNextTab();
                        _this.setFocusedItemByIndex(nextTab);
                    }
                    break;
                case KeyCodes.ARROW_DOWN:
                    if (!isAnyDropdownOpen && !TabPanel.isItemOfDropdownType(focusedTab)) {
                        var nextTab = _this.getNextTab();
                        _this.setFocusedItemByIndex(nextTab);
                    }
                    break;
                case KeyCodes.TAB:
                    var activeItemIndex = _this.getActiveItemIndex();
                    if (activeItemIndex >= 0 &&
                        ((activeItemIndex < focusedItemIndex && event.shiftKey) ||
                            (activeItemIndex > focusedItemIndex && !event.shiftKey))) {
                        _this.setFocusedItemByIndex(activeItemIndex);
                        event.preventDefault();
                    }
                    break;
                case KeyCodes.ENTER:
                case KeyCodes.SPACE:
                    if (!isAnyDropdownOpen && TabPanel.isItemCanBeFocusedWithKeyboard(focusedTab)) {
                        _this.setActiveItem(focusedTab, event);
                        event.preventDefault();
                    }
                    break;
            }
        };
        _this.setActiveItem = function (focusedTab, event) {
            var focusedItem;
            var target = event.target;
            if (TabPanel.isItemOfTabItemType(focusedTab)) {
                focusedItem = focusedTab;
            }
            else {
                var navDropdownNode = target.parentNode.parentNode;
                var index = TabPanel.getChildIndex(navDropdownNode, target);
                var children = cleanEmptyChildren(focusedTab.props.children);
                focusedItem = children[index];
            }
            if (isEmpty(focusedItem)) {
                return;
            }
            var activeTabPath = TabPanel.getItemPath(focusedItem);
            _this.activatePath(activeTabPath);
            var _a = focusedItem.props, eventKey = _a.eventKey, onClick = _a.onClick, onSelect = _a.onSelect;
            if (onSelect) {
                onSelect(eventKey, event);
            }
            if (onClick) {
                onClick();
            }
        };
        _this.activatePath = function (activeTabPath) {
            if (activeTabPath) {
                _this.context.router.push(activeTabPath);
            }
        };
        _this.handleFocus = function (event) {
            // we need this to have an ability to move out a focus from the panel with 'Shift+Tab' press
            _this.setState({
                panelTabIndex: -1
            });
            var focusedItemIndex = _this.state.focusedItemIndex;
            var tabPanelNode = ReactDOM.findDOMNode(_this);
            if (tabPanelNode === event.target) {
                _this.focusToItemNodeByIndex(focusedItemIndex);
            }
        };
        _this.handleFocusOut = function (event) {
            // this allows to get a focus to the panel from another elements after it looses a focus
            _this.setState({
                panelTabIndex: 0
            });
        };
        _this.handleDropdownToggle = function (dropdownId, isOpen) {
            _this.setState(function (state) {
                var isAnyDropdownOpen;
                var dropdownOpenStatuses = state.dropdownOpenStatuses;
                dropdownOpenStatuses[dropdownId] = isOpen;
                isAnyDropdownOpen = includes(dropdownOpenStatuses, true);
                return {
                    dropdownOpenStatuses: dropdownOpenStatuses,
                    isAnyDropdownOpen: isAnyDropdownOpen
                };
            });
        };
        return _this;
    }
    TabPanel.getChildIndex = function (containerNode, childNode) {
        var index = -1;
        var childrenArray = Array.from(containerNode.children);
        while (index === -1 && childNode !== null) {
            index = childrenArray.indexOf(childNode);
            childNode = childNode.parentNode;
        }
        return index;
    };
    TabPanel.getItemPath = function (item) {
        if (isEmpty(item) || isEmpty(item.props)) {
            return '';
        }
        var to = item.props.to;
        return (to && (to.pathname || to)) || '';
    };
    TabPanel.isItemCanBeFocusedWithKeyboard = function (item) {
        var isAllowedByDefault = TabPanel.isItemOfDropdownType(item) || TabPanel.isItemOfTabItemType(item);
        return isAllowedByDefault || item.props.role in TAB_PANEL_ITEM_ROLES;
    };
    TabPanel.isItemOfDropdownType = function (item) {
        return item && isElementHasType(item, NavDropdown);
    };
    TabPanel.isItemOfTabItemType = function (item) {
        return item && isElementHasType(item, TabItem);
    };
    TabPanel.prototype.getChildContext = function () {
        return {
            isStyledAsTab: this.isStyledAsTab
        };
    };
    TabPanel.prototype.componentDidMount = function () {
        this.focusActiveItem();
        // we need to handle focusout instead of onblur, see more here: https://github.com/facebook/react/issues/6410
        var tabPanel = ReactDOM.findDOMNode(this);
        tabPanel.addEventListener('focusout', this.handleFocusOut);
    };
    TabPanel.prototype.componentDidUpdate = function (previousProps, previousState) {
        if (this.isStyledAsTab()) {
            var previousFocusedItemIndex = previousState.focusedItemIndex;
            var _a = this.state, focusedItemIndex = _a.focusedItemIndex, isDropdownOpen = _a.isDropdownOpen;
            if (previousFocusedItemIndex !== focusedItemIndex && !isDropdownOpen) {
                this.focusToItemNodeByIndex(focusedItemIndex);
            }
        }
    };
    TabPanel.prototype.focusToItemNodeByIndex = function (focusedItemIndex) {
        var childNodes = ReactDOM.findDOMNode(this).children;
        var activeNode = childNodes[focusedItemIndex];
        if (activeNode) {
            activeNode.firstChild.focus();
        }
    };
    TabPanel.prototype.focusActiveItem = function () {
        var activeItemIndex = this.getActiveItemIndex();
        this.setFocusedItemByIndex(activeItemIndex);
        this.focusToItemNodeByIndex(activeItemIndex);
    };
    TabPanel.prototype.getActiveItemIndex = function () {
        var _this = this;
        var _a = this.props, activeKey = _a.activeKey, rawChildren = _a.children;
        var children = cleanEmptyChildren(rawChildren);
        var activeItemIndex;
        if (activeKey === null) {
            activeItemIndex = children.findIndex(function (child) {
                return child &&
                    (child.props.active ||
                        (_this.context.router &&
                            _this.context.router.isActive(TabPanel.getItemPath(child), false)));
            });
        }
        else {
            activeItemIndex = children.findIndex(function (child) { return child && child.props.eventKey === activeKey; });
        }
        return activeItemIndex;
    };
    TabPanel.prototype.getPreviousTab = function () {
        var rawChildren = this.props.children;
        var children = cleanEmptyChildren(rawChildren);
        var focusedItemIndex = this.state.focusedItemIndex;
        var previousItemIndex = focusedItemIndex - 1;
        var isPreviousChildPresent = previousItemIndex >= 0;
        var lastChildIndex = children.length - 1;
        if (isPreviousChildPresent &&
            TabPanel.isItemCanBeFocusedWithKeyboard(children[previousItemIndex])) {
            return previousItemIndex;
        }
        return TabPanel.isItemCanBeFocusedWithKeyboard(children[lastChildIndex])
            ? lastChildIndex
            : lastChildIndex - 1;
    };
    TabPanel.prototype.getNextTab = function () {
        var rawChildren = this.props.children;
        var children = cleanEmptyChildren(rawChildren);
        var focusedItemIndex = this.state.focusedItemIndex;
        var nextItemIndex = focusedItemIndex + 1;
        var isNextChildPresent = nextItemIndex < children.length;
        if (isNextChildPresent &&
            TabPanel.isItemCanBeFocusedWithKeyboard(children[nextItemIndex])) {
            return nextItemIndex;
        }
        return 0;
    };
    TabPanel.prototype.getChildren = function () {
        var _this = this;
        var rawChildren = this.props.children;
        var children = cleanEmptyChildren(rawChildren);
        return Children.map(children, function (child, index) {
            if (TabPanel.isItemOfDropdownType(child)) {
                var childProps = {
                    onToggle: function (isOpen) { return _this.handleDropdownToggle(index, isOpen); }
                };
                return cloneElement(child, childProps);
            }
            return child;
        });
    };
    TabPanel.prototype.render = function () {
        var _a = this.props, testAutomationId = _a.testAutomationId, centered = _a.centered, noBorder = _a.noBorder, topMenu = _a.topMenu, clearRightPadding = _a.clearRightPadding, clearLeftPadding = _a.clearLeftPadding, clearLeftWrapperPadding = _a.clearLeftWrapperPadding, clearRightWrapperPadding = _a.clearRightWrapperPadding, fullWidthBorder = _a.fullWidthBorder, noPadding = _a.noPadding, className = _a.className, preserveBottomBorder = _a.preserveBottomBorder, props = __rest(_a, ["testAutomationId", "centered", "noBorder", "topMenu", "clearRightPadding", "clearLeftPadding", "clearLeftWrapperPadding", "clearRightWrapperPadding", "fullWidthBorder", "noPadding", "className", "preserveBottomBorder"]);
        var panelTabIndex = this.state.panelTabIndex;
        className = classnames({
            'rc-nav-centered': centered,
            'rc-nav-noHorizontalPadding': noPadding,
            'rc-nav-noBorder': noBorder,
            'rc-nav-fullWidthBorder': !noBorder && fullWidthBorder,
            'rc-nav-topMenu': topMenu,
            'rc-nav-clearRightPadding': clearRightPadding,
            'rc-nav-clearLeftPadding': clearLeftPadding,
            'rc-nav-clearLeftWrapperPadding': clearLeftWrapperPadding,
            'rc-nav-clearRightWrapperPadding': clearRightWrapperPadding,
            'rc-nav-preserveBottomBorder': preserveBottomBorder
        }, className);
        return (React.createElement(Nav, __assign({ bsStyle: "tabs", className: className, "data-test-automation-id": testAutomationId, role: "tablist", tabIndex: panelTabIndex, onFocus: this.handleFocus, onClick: this.handleClick, onKeyDown: this.handleKeyDown }, props), this.getChildren()));
    };
    TabPanel.propTypes = {
        testAutomationId: PropTypes.string,
        children: PropTypes.node.isRequired,
        centered: PropTypes.bool,
        noBorder: PropTypes.bool,
        topMenu: PropTypes.bool,
        clearRightPadding: PropTypes.bool,
        clearLeftPadding: PropTypes.bool,
        clearLeftWrapperPadding: PropTypes.bool,
        clearRightWrapperPadding: PropTypes.bool,
        fullWidthBorder: PropTypes.bool,
        noPadding: PropTypes.bool,
        preserveBottomBorder: PropTypes.bool,
        className: PropTypes.string,
        activeKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
        bsStyle: PropTypes.oneOf([
            TAB_PANEL_STYLES.TABS,
            TAB_PANEL_STYLES.MENU,
            TAB_PANEL_STYLES.PILLS
        ])
    };
    TabPanel.defaultProps = {
        testAutomationId: 'tabs',
        centered: false,
        noBorder: false,
        topMenu: false,
        clearRightPadding: false,
        clearLeftPadding: false,
        clearLeftWrapperPadding: false,
        clearRightWrapperPadding: false,
        fullWidthBorder: false,
        preserveBottomBorder: false,
        noPadding: false,
        className: null,
        activeKey: null,
        bsStyle: TAB_PANEL_STYLES.TABS
    };
    TabPanel.contextTypes = {
        router: PropTypes.object
    };
    TabPanel.childContextTypes = {
        isStyledAsTab: PropTypes.func
    };
    return TabPanel;
}(React.Component));
export { TabPanel };
//# sourceMappingURL=TabPanel.js.map