import * as React from 'react';
import { debounce } from 'lodash';

const PAGE = {
    FIRST: 'FIRST',
    PREVIOUS: 'PREVIOUS',
    NEXT: 'NEXT',
    LAST: 'LAST',
};

const allowedKeys = [
    '1',
    '2',
    '3',
    '4',
    '5',
    '6',
    '7',
    '8',
    '9',
    '0',
    'Backspace',
    'ArrowUp',
    'ArrowDown',
    'ArrowLeft',
    'ArrowRight',
];
const allowedKeyCodes = [
    8, // Backspace
    37, // ArrowLeft
    38, // ArrowUp
    39, // ArrowRight
    40, // ArrowDown
];
const keyCodeIsAllowed = (keyCode) => {
    return !!(
        (keyCode >= 48 && keyCode <= 57) ||
        allowedKeyCodes.includes(keyCode)
    );
};

export interface MmuiPaginationInputProps {
    pageNumber: string;
    staticUrl: string;
    totalPages: number;
    updateCurrentPage: (pageNumber: number) => void;
}

export class MmuiPaginationInputComponent extends React.Component<MmuiPaginationInputProps> {
    protected pageNumberInput: HTMLInputElement;

    componentDidUpdate(prevProps) {
        if (prevProps.pageNumber != this.props.pageNumber) {
            this.pageNumberInput?.select();
        }
    }

    updateCurrentPageDebounced = debounce((value) => {
        this.props.updateCurrentPage(value);
    }, 500);

    handleKeyDown = (e) => {
        if (!(allowedKeys.includes(e.key) || keyCodeIsAllowed(e.which))) {
            // e.which is for older browser support
            e.preventDefault();
        }
    };

    handleKeyUp = (e) => {
        let value = parseInt(e.target.value);

        if (value < 1) {
            value = 1;
        } else if (value > this.props.totalPages) {
            value = this.props.totalPages;
        } else if (!value) {
            return;
        }
        this.updateCurrentPageDebounced(value);
    };

    onCurrentPageUpdate = (e, context) => {
        e.preventDefault();
        switch (context) {
            case PAGE.FIRST:
                this.props.updateCurrentPage(1);
                break;
            case PAGE.PREVIOUS:
                this.props.updateCurrentPage(
                    parseInt(this.props.pageNumber) - 1
                );
                break;
            case PAGE.NEXT:
                this.props.updateCurrentPage(
                    parseInt(this.props.pageNumber) + 1
                );
                break;
            case PAGE.LAST:
                this.props.updateCurrentPage(this.props.totalPages);
                break;
        }
    };

    handleBlur = () => {
        const boolValue = !!this.pageNumberInput.value;
        if (boolValue) return; // Reset the input value only if the input is empty
        this.pageNumberInput.value = this.props.pageNumber;
    };

    render() {
        return (
            <nav
                className="mmui-pagination-input d-flex mb-3"
                aria-label="Pagination"
            >
                <div
                    className="d-flex align-items-center mx-auto"
                    aria-live="polite"
                >
                    <div
                        style={{
                            visibility:
                                +this.props.pageNumber > 1
                                    ? 'visible'
                                    : 'hidden',
                        }}
                        className="d-flex"
                    >
                        <button
                            className="btn d-flex align-items-center position-relative"
                            aria-label="First Page"
                            onClick={(e) =>
                                this.onCurrentPageUpdate(e, PAGE.FIRST)
                            }
                        >
                            <i className="fa fa-angle-double-left"></i>
                            <span className="sr-only">First Page</span>
                        </button>
                        <button
                            className="btn d-flex align-items-center position-relative"
                            aria-label="Previous"
                            onClick={(e) =>
                                this.onCurrentPageUpdate(e, PAGE.PREVIOUS)
                            }
                        >
                            <i className="fa fa-angle-left"></i>
                            <span className="sr-only">Previous Page</span>
                        </button>
                    </div>
                    <span className="user-select-none">Page</span>
                    {!(this.props.totalPages == 1) ? (
                        <input
                            className="text-center"
                            aria-placeholder="Page Input"
                            type="number"
                            min={1}
                            max={this.props.totalPages}
                            size={2}
                            aria-label={this.props.pageNumber}
                            onKeyDown={this.handleKeyDown}
                            onKeyUp={this.handleKeyUp}
                            onPaste={(e) => e.preventDefault()}
                            onBlur={this.handleBlur}
                            ref={(input) => {
                                this.pageNumberInput = input;
                            }}
                            defaultValue={this.props.pageNumber}
                            key={this.props.pageNumber}
                            inputMode="numeric"
                            pattern="[0-9]*"
                        />
                    ) : (
                        <span>&nbsp;1&nbsp;</span>
                    )}
                    <span className="user-select-none">
                        of {this.props.totalPages}
                    </span>

                    <div
                        style={{
                            visibility:
                                +this.props.pageNumber != this.props.totalPages
                                    ? 'visible'
                                    : 'hidden',
                        }}
                        className="d-flex"
                    >
                        <button
                            className="btn d-flex align-items-center position-relative"
                            aria-label="Next"
                            onClick={(e) =>
                                this.onCurrentPageUpdate(e, PAGE.NEXT)
                            }
                        >
                            <i className="fa fa-angle-right"></i>
                            <span className="sr-only">Next Page</span>
                        </button>
                        <button
                            className="btn d-flex align-items-center position-relative"
                            aria-label="Last Page"
                            onClick={(e) =>
                                this.onCurrentPageUpdate(e, PAGE.LAST)
                            }
                        >
                            <i className="fa fa-angle-double-right"></i>
                            <span className="sr-only">Last Page</span>
                        </button>
                    </div>
                </div>
            </nav>
        );
    }
}
