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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import React from 'react';
import warning from 'warning';
import { isInstanceOf } from '../../lib/isInstanceOf.js';
import { isKeyArrowLeft, isKeyArrowRight, isKeyEnter } from '../../lib/events/keyboard/identifiers.js';
import { locale } from '../../lib/locale/decorators.js';
import { KeyListener } from '../../lib/events/keyListener.js';
import { emptyHandler } from '../../lib/utils.js';
import { ThemeContext } from '../../lib/theming/ThemeContext.js';
import { CommonWrapper } from '../../internal/CommonWrapper/index.js';
import { rootNode } from '../../lib/rootNode/index.js';
import { createPropsGetter } from '../../lib/createPropsGetter.js';
import { getVisualStateDataAttributes } from '../../internal/CommonWrapper/utils/getVisualStateDataAttributes.js';
import { ResponsiveLayout } from '../ResponsiveLayout/index.js';
import { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';
import { getStyles } from './Paging.styles.js';
import * as NavigationHelper from './NavigationHelper.js';
import { getItems } from './PagingHelper.js';
import { PagingLocaleHelper } from './locale/index.js';
import { PagingDefaultComponent } from './PagingDefaultComponent.js';
import { ForwardIcon, ForwardIconMobile } from './ForwardIcon.js';
import { DotsIcon } from './DotsIcon.js';
var IGNORE_EVENT_TAGS = ['input', 'textarea'];
export var PagingDataTids = {
    root: 'Paging__root',
    dots: 'Paging__dots',
    forwardLink: 'Paging__forwardLink',
    pageLinkWrapper: 'Paging__pageLinkWrapper',
    pageLink: 'Paging__pageLink',
};
/**
 * Постраничная навигация `Paging` (пейджинг или пагинация) — способ представления большого количества однородной информации, когда контент разбивается на страницы.
 */
var Paging = /** @class */ (function (_super) {
    __extends(Paging, _super);
    function Paging() {
        var _this = _super !== null && _super.apply(this, arguments) || this;
        _this.getProps = createPropsGetter(Paging_1.defaultProps);
        _this.state = {
            focusedByTab: false,
            focusedItem: null,
            keyboardControl: _this.getProps().useGlobalListener,
        };
        _this.addedGlobalListener = false;
        _this.container = null;
        _this.renderItem = function (item, index) {
            var focused = _this.getFocusedItem() === item;
            switch (item) {
                case '.': {
                    var key = "dots".concat(index < 5 ? 'Left' : 'Right');
                    return _this.renderDots(key);
                }
                case 'forward': {
                    var disabled = _this.isItemDisabled(item);
                    return _this.renderForwardLink(disabled, focused);
                }
                default: {
                    var active = _this.props.activePage === item;
                    return _this.renderPageLink(item, active, focused);
                }
            }
        };
        _this.renderDots = function (key) {
            var _a;
            return (React.createElement("span", { "data-tid": PagingDataTids.dots, key: key, className: _this.cx(_this.styles.dots(_this.theme), _this.sizeClassNames.dots, (_a = {},
                    _a[_this.styles.dotsDisabled(_this.theme)] = _this.props.disabled,
                    _a)) }, _this.getDotsIcon()));
        };
        _this.renderForwardLink = function (disabled, focused) {
            var _a;
            var classNames = _this.cx(_this.styles.pageLink(_this.theme), _this.sizeClassNames.pageLink, _this.styles.forwardLink(_this.theme), _this.sizeClassNames.forwardLink, (_a = {},
                _a[_this.styles.pageLinkFocused(_this.theme)] = focused,
                _a[_this.styles.forwardLinkDisabled(_this.theme)] = disabled || _this.props.disabled,
                _a));
            var Component = _this.getProps().component;
            var forward = _this.locale.forward;
            var forwardIcon = _this.getForwardIcon();
            return (React.createElement(Component, __assign({ key: 'forward', "data-tid": PagingDataTids.forwardLink, active: false, className: classNames, onClick: disabled ? emptyHandler : _this.goForward, tabIndex: -1, pageNumber: 'forward' }, getVisualStateDataAttributes({ disabled: disabled })),
                !_this.isMobile && (_this.props.caption || forward),
                forwardIcon));
        };
        _this.renderPageLink = function (pageNumber, active, focused) {
            var _a;
            var disabled = _this.props.disabled;
            var classNames = _this.cx(_this.styles.pageLink(_this.theme), _this.sizeClassNames.pageLink, (_a = {},
                _a[_this.styles.pageLinkFocused(_this.theme)] = focused,
                _a[_this.styles.pageLinkDisabled(_this.theme)] = disabled,
                _a[_this.styles.pageLinkCurrent(_this.theme)] = active,
                _a[_this.styles.pageLinkCurrentDisabled(_this.theme)] = active && disabled,
                _a));
            var Component = _this.getProps().component;
            var handleClick = function () { return _this.goToPage(pageNumber); };
            return (React.createElement("span", __assign({ "data-tid": PagingDataTids.pageLinkWrapper, key: pageNumber, className: _this.styles.pageLinkWrapper() }, getVisualStateDataAttributes({ active: active, disabled: disabled })),
                React.createElement(Component, { "data-tid": PagingDataTids.pageLink, active: active, className: classNames, onClick: handleClick, tabIndex: -1, pageNumber: pageNumber }, pageNumber),
                active && !_this.isMobile && _this.renderNavigationHint()));
        };
        _this.renderNavigationHint = function () {
            if (_this.props.withoutNavigationHint) {
                return null;
            }
            var keyboardControl = _this.state.keyboardControl;
            var canGoBackward = _this.canGoBackward();
            var canGoForward = _this.canGoForward();
            var hint = null;
            if (keyboardControl && (canGoBackward || canGoForward)) {
                hint = (React.createElement(React.Fragment, null,
                    React.createElement("span", { className: canGoBackward ? '' : _this.styles.transparent() }, '←'),
                    React.createElement("span", null, NavigationHelper.getKeyName()),
                    React.createElement("span", { className: canGoForward ? '' : _this.styles.transparent() }, '→')));
            }
            return React.createElement("div", { className: _this.styles.pageLinkHint(_this.theme) }, hint);
        };
        _this.handleMouseDown = function () {
            _this.setState({ focusedByTab: false, focusedItem: null });
        };
        _this.handleKeyDown = function (e) {
            if (e.shiftKey) {
                return;
            }
            var target = e.target;
            var isArrowLeft = isKeyArrowLeft(e);
            var isArrowRight = isKeyArrowRight(e);
            if (isInstanceOf(target, _this.globalObject.Element) &&
                (IGNORE_EVENT_TAGS.includes(target.tagName.toLowerCase()) || target.isContentEditable)) {
                return;
            }
            if (NavigationHelper.checkKeyPressed(e) && isArrowLeft) {
                _this.setState({ focusedItem: null }, _this.goBackward);
                return;
            }
            if (NavigationHelper.checkKeyPressed(e) && isArrowRight) {
                _this.setState({ focusedItem: null }, _this.goForward);
                return;
            }
            if (_this.container && _this.container === e.target) {
                if (isArrowLeft) {
                    _this.setState({ focusedByTab: true }, _this.moveFocusLeft);
                    return;
                }
                if (isArrowRight) {
                    _this.setState({ focusedByTab: true }, _this.moveFocusRight);
                    return;
                }
                if (isKeyEnter(e)) {
                    _this.executeItemAction(_this.getFocusedItem());
                    return;
                }
            }
        };
        _this.handleFocus = function () {
            var _a, _b;
            if (_this.props.disabled) {
                return;
            }
            _this.setState({ keyboardControl: true });
            // focus event fires before keyDown eventlistener
            // so we should check tabPressed in async way
            (_b = (_a = _this.globalObject).requestAnimationFrame) === null || _b === void 0 ? void 0 : _b.call(_a, function () {
                if (_this.keyListener.isTabPressed) {
                    _this.setState({ focusedByTab: true });
                }
            });
        };
        _this.handleBlur = function () {
            _this.setState({
                focusedByTab: false,
                keyboardControl: _this.getProps().useGlobalListener || false,
            });
        };
        _this.getItems = function () {
            return getItems(_this.props.activePage, _this.props.pagesCount, _this.isMobile).concat('forward');
        };
        _this.getFocusedItem = function () {
            if (!_this.state.focusedByTab) {
                return null;
            }
            var focusedItem = _this.state.focusedItem;
            if (focusedItem && _this.getItems().includes(focusedItem) && _this.isItemFocusable(focusedItem)) {
                return focusedItem;
            }
            return _this.props.activePage;
        };
        _this.isItemFocusable = function (item) {
            return !_this.isItemDisabled(item);
        };
        _this.isItemDisabled = function (item) {
            switch (item) {
                case '.':
                    return true;
                case 'forward':
                    return !_this.canGoForward();
                default:
                    return false;
            }
        };
        _this.executeItemAction = function (item) {
            if (item === 'forward') {
                _this.goForward();
            }
            if (typeof item === 'number') {
                _this.goToPage(item);
            }
        };
        _this.moveFocusLeft = function () {
            _this.moveFocus(-1);
        };
        _this.moveFocusRight = function () {
            _this.moveFocus(1);
        };
        _this.moveFocus = function (step) {
            var focusedItem = _this.getFocusedItem();
            var items = _this.getItems();
            var index = items.findIndex(function (x) { return x === focusedItem; });
            do {
                index = (index + step + items.length) % items.length;
            } while (!_this.isItemFocusable(items[index]));
            _this.setState({ focusedItem: items[index] });
        };
        _this.canGoBackward = function () {
            return _this.props.activePage > 1;
        };
        _this.canGoForward = function () {
            return _this.props.activePage < _this.props.pagesCount;
        };
        _this.goBackward = function () {
            _this.goToPage(_this.props.activePage - 1);
        };
        _this.goForward = function () {
            _this.goToPage(_this.props.activePage + 1);
        };
        _this.goToPage = function (pageNumber) {
            if (pageNumber >= 1 && pageNumber !== _this.props.activePage && pageNumber <= _this.props.pagesCount) {
                _this.props.onPageChange(pageNumber);
            }
        };
        _this.addGlobalListener = function () {
            var _a;
            if (_this.addedGlobalListener) {
                return;
            }
            (_a = _this.globalObject.document) === null || _a === void 0 ? void 0 : _a.addEventListener('keydown', _this.handleKeyDown);
            _this.addedGlobalListener = true;
        };
        _this.removeGlobalListener = function () {
            var _a;
            if (_this.addedGlobalListener) {
                (_a = _this.globalObject.document) === null || _a === void 0 ? void 0 : _a.removeEventListener('keydown', _this.handleKeyDown);
                _this.addedGlobalListener = false;
            }
        };
        _this.refContainer = function (element) {
            _this.container = element;
        };
        _this.getPagingSizeClassNames = function () {
            var size = _this.getSize();
            var defaultClassNames = {
                root: _this.styles.pagingSmall(_this.theme),
                dots: _this.styles.dotsSmall(_this.theme),
                forwardLink: _this.styles.forwardLinkSmall(_this.theme),
                pageLink: _this.styles.pageLinkSmall(_this.theme),
            };
            switch (size) {
                case 'small':
                    return defaultClassNames;
                case 'medium':
                    return {
                        root: _this.styles.pagingMedium(_this.theme),
                        dots: _this.styles.dotsMedium(_this.theme),
                        forwardLink: _this.isMobile
                            ? _this.styles.forwardLinkMediumMobile(_this.theme)
                            : _this.styles.forwardLinkMedium(_this.theme),
                        pageLink: _this.styles.pageLinkMedium(_this.theme),
                    };
                case 'large':
                    return {
                        root: _this.styles.pagingLarge(_this.theme),
                        dots: _this.styles.dotsLarge(_this.theme),
                        forwardLink: _this.isMobile
                            ? _this.styles.forwardLinkLargeMobile(_this.theme)
                            : _this.styles.forwardLinkLarge(_this.theme),
                        pageLink: _this.styles.pageLinkLarge(_this.theme),
                    };
                default:
                    warning(false, "Invalid size prop: '".concat(_this.props.size, "'"));
                    return defaultClassNames;
            }
        };
        _this.getDotsIcon = function () {
            var size = _this.getSize();
            return React.createElement(DotsIcon, { size: size });
        };
        _this.getForwardIcon = function () {
            var size = _this.getSize();
            var iconSize = size;
            return _this.isMobile ? (React.createElement(ForwardIconMobile, { size: iconSize })) : (React.createElement(ForwardIcon, { size: iconSize, style: { marginLeft: 4 } }));
        };
        _this.getSize = function () {
            if (_this.props.size) {
                return _this.isMobile && _this.props.size === 'small' ? 'medium' : _this.props.size;
            }
            var defaultSize = 'small';
            return _this.isMobile ? 'medium' : defaultSize;
        };
        return _this;
    }
    Paging_1 = Paging;
    Paging.isForward = function (pageNumber) {
        return pageNumber === 'forward';
    };
    Paging.prototype.componentDidMount = function () {
        this.keyListener = new KeyListener(this.globalObject);
        var useGlobalListener = this.getProps().useGlobalListener;
        if (useGlobalListener) {
            this.addGlobalListener();
        }
    };
    Paging.prototype.componentDidUpdate = function (prevProps) {
        var useGlobalListener = this.getProps().useGlobalListener;
        if (!prevProps.useGlobalListener && useGlobalListener) {
            this.addGlobalListener();
        }
        if (prevProps.useGlobalListener && !useGlobalListener) {
            this.removeGlobalListener();
        }
        if (prevProps.useGlobalListener !== useGlobalListener) {
            this.setState({
                keyboardControl: useGlobalListener,
            });
        }
    };
    Paging.prototype.componentWillUnmount = function () {
        this.removeGlobalListener();
    };
    Paging.prototype.render = function () {
        var _this = this;
        if (this.props.pagesCount < 2) {
            return null;
        }
        this.styles = getStyles(this.emotion);
        return (React.createElement(ThemeContext.Consumer, null, function (theme) {
            _this.theme = theme;
            return (React.createElement(ResponsiveLayout, null, function (_a) {
                var isMobile = _a.isMobile;
                _this.isMobile = isMobile;
                _this.sizeClassNames = _this.getPagingSizeClassNames();
                return _this.renderMain();
            }));
        }));
    };
    Paging.prototype.renderMain = function () {
        var _a;
        var _this = this;
        var useGlobalListener = this.getProps().useGlobalListener;
        return (React.createElement(CommonWrapper, __assign({ rootNodeRef: this.setRootNode }, this.props, getVisualStateDataAttributes({ disabled: this.props.disabled })),
            React.createElement("span", { tabIndex: this.props.disabled ? -1 : 0, "data-tid": PagingDataTids.root, className: this.cx(this.styles.paging(), this.sizeClassNames.root, (_a = {},
                    _a[this.styles.pagingMobile()] = this.isMobile,
                    _a[this.styles.pagingDisabled()] = this.props.disabled,
                    _a)), onKeyDown: useGlobalListener ? undefined : this.handleKeyDown, onFocus: this.handleFocus, onBlur: this.handleBlur, onMouseDown: this.handleMouseDown, ref: this.refContainer }, this.getItems().map(function (item, index) { return _this.renderItem(item, index); }))));
    };
    var Paging_1;
    Paging.__KONTUR_REACT_UI__ = 'Paging';
    Paging.displayName = 'Paging';
    Paging.defaultProps = {
        component: PagingDefaultComponent,
        useGlobalListener: false,
    };
    Paging = Paging_1 = __decorate([
        withRenderEnvironment,
        rootNode,
        locale('Paging', PagingLocaleHelper)
    ], Paging);
    return Paging;
}(React.PureComponent));
export { Paging };
//# sourceMappingURL=Paging.js.map