import * as React from 'react';
import { st, classes } from './PaginationCore.st.css.js';
import { DataHooks } from './constants';
import { calculateWidth, getId, measureAndSetRootMinWidth } from './utils';
import { PageStrip } from './PageStrip';
import { filterDataProps } from '../../utils/propsUtils';
const upperCaseFirst = (str) => str[0].toUpperCase() + str.slice(1);
class PaginationCore extends React.Component {
    constructor() {
        super(...arguments);
        this.getMaxPagesToShow = () => {
            if (this.props.maxPagesToShow) {
                return this.props.maxPagesToShow;
            }
            if (this.props.responsive) {
                return 20;
            }
            return 7;
        };
        this.state = {
            pageInputValue: String(this.props.currentPage),
            pageInputHasError: false,
        };
        this.handlePageInputChange = (e) => {
            this.setState({
                pageInputValue: e.target.value,
                pageInputHasError: false,
            });
        };
        this.handlePageInputKeyDown = (event) => {
            // Enter
            if (event.key === 'Enter') {
                const page = Number(this.state.pageInputValue);
                if (page !== this.props.currentPage) {
                    if (1 <= page && page <= this.props.totalPages) {
                        this.props.onChange && this.props.onChange({ event, page });
                    }
                    else {
                        this.setState({ pageInputHasError: true });
                    }
                }
            }
        };
        this.handlePageInputBlur = () => {
            this.setState({
                pageInputValue: String(this.props.currentPage),
                pageInputHasError: false,
            });
        };
        this.handlePageClick = (event, page) => {
            this.props.onChange && this.props.onChange({ event, page });
        };
        this.handlePageKeyDown = (event, page) => {
            // Enter or Space
            if (event.key === 'Enter' || event.key === 'Space') {
                this.props.onChange && this.props.onChange({ event, page });
            }
        };
    }
    updateRootMinWidth() {
        this.rootNode &&
            this.props.paginationMode &&
            measureAndSetRootMinWidth(this.rootNode, this.props.paginationMode, this.props.id);
    }
    componentDidMount() {
        this.props.updateResponsiveLayout && this.updateRootMinWidth();
    }
    componentDidUpdate() {
        this.props.updateResponsiveLayout && this.updateRootMinWidth();
    }
    getId(elementName = '') {
        return getId(this.props.id, elementName);
    }
    renderPageStrip() {
        return (React.createElement(PageStrip, { id: this.props.id, totalPages: this.props.totalPages || 0, currentPage: this.props.currentPage || 0, maxPagesToShow: this.getMaxPagesToShow() || 0, showFirstPage: !!this.props.showFirstPage, showLastPage: !!this.props.showLastPage, responsive: !!this.props.responsive, pageUrl: this.props.pageUrl, gapLabel: this.props.gapLabel || '', onPageClick: this.handlePageClick, onPageKeyDown: this.handlePageKeyDown, updateResponsiveLayout: this.props.updateResponsiveLayout, disabled: !!this.props.disabled }));
    }
    renderPages() {
        switch (this.props.paginationMode) {
            case "input" /* PaginationCoreMode.Input */:
                return this.renderPageForm();
            case "compact" /* PaginationCoreMode.Compact */:
                return this.renderPageCompact();
            case "pages" /* PaginationCoreMode.Pages */:
            default:
                return this.renderPageStrip();
        }
    }
    renderPageCompact() {
        return (React.createElement("div", { "data-hook": DataHooks.pageCompact, id: this.getId('pageCompact'), className: classes.compact },
            React.createElement("span", { id: this.getId('currentPage'), "data-hook": DataHooks.currentPage }, this.props.currentPage),
            React.createElement("span", { id: this.getId('slash'), className: classes.slash, "data-hook": DataHooks.slashLabel }, this.props.slashLabel),
            React.createElement("span", { id: this.getId('totalPages'), "data-hook": DataHooks.totalPages }, this.props.totalPages)));
    }
    renderPageForm() {
        return (React.createElement("div", { "data-hook": DataHooks.pageForm, id: this.getId('pageForm'), className: classes.pageForm, dir: "ltr" },
            React.createElement("input", { id: this.getId('pageInput'), "data-hook": DataHooks.pageInput, type: "number", className: classes.pageInput, min: 1, max: this.props.totalPages, value: this.state.pageInputValue, disabled: this.props.disabled, onChange: this.handlePageInputChange, onKeyDown: this.handlePageInputKeyDown, "aria-label": 'Page number, select a number between 1 and ' +
                    this.props.totalPages, onBlur: this.handlePageInputBlur, style: { width: calculateWidth(this.props.totalPages) } }),
            this.props.showInputModeTotalPages && [
                React.createElement("span", { key: "slash", id: this.getId('slash'), className: classes.slash }, this.props.slashLabel),
                React.createElement("span", { key: "total-pages", id: this.getId('totalPages'), "data-hook": DataHooks.totalPages, className: classes.totalPages }, this.props.totalPages),
            ]));
    }
    renderEmptyButton(type) {
        let btnClass = '';
        switch (type) {
            case "previous" /* ButtonType.Prev */: {
                btnClass = classes.emptyButtonPrevious;
                break;
            }
            case "next" /* ButtonType.Next */: {
                btnClass = classes.emptyButtonNext;
                break;
            }
            default:
        }
        return (React.createElement("div", { "data-hook": DataHooks[type], className: st(classes.emptyButton, btnClass) }));
    }
    renderNavButton(type) {
        const { currentPage, totalPages, pageUrl } = this.props;
        const disabled = this.props.disabled ||
            ((type === "first" /* ButtonType.First */ || type === "previous" /* ButtonType.Prev */) &&
                (currentPage || 0) <= 1) ||
            ((type === "last" /* ButtonType.Last */ || type === "next" /* ButtonType.Next */) &&
                (currentPage || 0) >= totalPages);
        const [btnClass, label, page] = {
            ["previous" /* ButtonType.Prev */]: [
                classes.navButtonPrevious,
                this.props.previousLabel,
                (currentPage || 0) - 1,
            ],
            ["next" /* ButtonType.Next */]: [
                classes.navButtonNext,
                this.props.nextLabel,
                (currentPage || 0) + 1,
            ],
            ["first" /* ButtonType.First */]: [classes.navButtonFirst, this.props.firstLabel, 1],
            ["last" /* ButtonType.Last */]: [
                classes.navButtonLast,
                this.props.lastLabel,
                totalPages,
            ],
        }[type];
        return (React.createElement("a", { "data-hook": DataHooks[type], id: this.getId('navButton' + upperCaseFirst(type)), className: st(classes.navButton, { disabled }, btnClass), "aria-label": upperCaseFirst(type) + ' Page', "aria-disabled": disabled, tabIndex: disabled || pageUrl ? undefined : 0, onClick: disabled ? undefined : event => this.handlePageClick(event, page), onKeyDown: disabled ? undefined : event => this.handlePageKeyDown(event, page), href: !disabled && pageUrl ? pageUrl(page) : undefined }, label));
    }
    UNSAFE_componentWillReceiveProps(nextProps) {
        this.setState({
            pageInputValue: String(nextProps.currentPage),
            pageInputHasError: false,
        });
    }
    render() {
        const { disabled, showFirstLastNavButtons, showNextLabel, showPreviousLabel, width, style: inlineStyle, } = this.props;
        const styleStates = {
            disabled,
            error: this.state.pageInputHasError,
        };
        return (React.createElement("nav", { ref: el => {
                this.rootNode = el;
            }, id: this.getId(''), "aria-label": "PaginationCore Navigation", "aria-disabled": disabled, dir: this.props.rtl ? 'rtl' : undefined, onClick: this.props.onClick, onDoubleClick: this.props.onDoubleClick, onMouseEnter: this.props.onMouseEnter, onMouseLeave: this.props.onMouseLeave, style: inlineStyle || { width }, className: st(classes.root, styleStates, this.props.className), ...filterDataProps(this.props) },
            showFirstLastNavButtons && this.renderNavButton("first" /* ButtonType.First */),
            showPreviousLabel
                ? this.renderNavButton("previous" /* ButtonType.Prev */)
                : this.renderEmptyButton("previous" /* ButtonType.Prev */),
            this.renderPages(),
            showNextLabel
                ? this.renderNavButton("next" /* ButtonType.Next */)
                : this.renderEmptyButton("next" /* ButtonType.Next */),
            showFirstLastNavButtons && this.renderNavButton("last" /* ButtonType.Last */)));
    }
}
PaginationCore.displayName = 'PaginationCore';
PaginationCore.defaultProps = {
    currentPage: 1,
    showFirstLastNavButtons: false,
    showFirstPage: false,
    showLastPage: false,
    showNextLabel: true,
    showPreviousLabel: true,
    responsive: false,
    paginationMode: 'pages',
    showInputModeTotalPages: false,
    disabled: false,
    // dir="rtl" automatically flips the direction of less-than and more-than signs.
    // If we decide to use different labels we need to add conditional logic.
    firstLabel: '<<',
    lastLabel: '>>',
    previousLabel: '<',
    nextLabel: '>',
    gapLabel: '...',
    slashLabel: '\u00A0/\u00A0',
};
export default PaginationCore;
//# sourceMappingURL=PaginationCore.js.map