import React, { FC, memo }                    from 'react';
import { Icon }                               from '../../../';
import { cn }                                 from '../../util/bem';
import { FormSizesType, SizeType }            from '../../util/global-props';
import { findNextElement, focus, formatTime } from './time-picker.utils';
import './time-picker.component.scss';

type ValueType = {
    hours: number;
    minutes: number;
};

type TimePickerPropsType = {
    margin?: SizeType;
    size?: FormSizesType;
    after?: React.ReactNode;
    disabled?: boolean;

    value: ValueType;
    onChange: (v: ValueType) => any;
}

const className = cn('time-picker');

export const TimePicker: FC<TimePickerPropsType> = memo(((props) => {
    const changeDispatch = (key: string | null, value: number) => {
        if (!key) {
            return;
        }

        props.onChange({ ...props.value, [ key ]: value });
    };

    const handleFocus = (event: React.ChangeEvent<HTMLInputElement>) => {
        event.target.select();
    };

    const handleBlur = (event: React.ChangeEvent<HTMLInputElement>) => {
        const max = +(event.target.getAttribute('max') || '10');
        const min = +(event.target.getAttribute('min') || '0');

        let value = +event.target.value;
        if (value > +max) {
            value = max;
        } else if (value < +min) {
            value = min;
        }

        changeDispatch(event.target.getAttribute('name'), value);
    };

    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        const value = +formatTime(event.target.value);

        changeDispatch(event.target.getAttribute('name'), value);
    };

    const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
        switch (event.key) {
            case 'ArrowDown':
            case 'ArrowUp': {
                const input = event.target as HTMLInputElement;
                const name = input.getAttribute('name');
                const max = +(input.getAttribute('max') || '10');
                const min = +(input.getAttribute('min') || '0');
                const currentValue = +input.value;
                const nextValue = event.key === 'ArrowUp' ? currentValue + 1 : currentValue - 1;

                if (nextValue > max) {
                    event.preventDefault();
                    changeDispatch(name, min);
                    return;
                }
                if (nextValue < min) {
                    event.preventDefault();
                    changeDispatch(name, max);
                }
                break;
            }

            case 'ArrowLeft':
            case 'ArrowRight': {
                event.preventDefault();

                const input = event.target as HTMLInputElement;
                const property = event.key === 'ArrowLeft' ? 'previousElementSibling' : 'nextElementSibling';
                const nextInput = findNextElement(input, property);
                focus(nextInput);
                break;
            }
            default:
        }
    };

    const handleKeyUp = (event: React.KeyboardEvent<HTMLInputElement>) => {
        const input = event.target as HTMLInputElement;

        const isNumberKey = !Number.isNaN(parseInt(event.key, 10));
        if (!isNumberKey) {
            return;
        }

        const { value } = input;
        if (value[ 0 ] === '0') {
            return;
        }

        const max = input.getAttribute('max') || '10';
        if ((+value * 10 > +max) || (value.length >= max.length)) {
            const property = 'nextElementSibling';
            const nextInput = findNextElement(input, property);
            focus(nextInput);
        }
    };

    return (
        <div
            className={ className({
                size:   props.size,
                margin: props.margin
            }) }
        >
            <div className={ className('wrapper') }>
                <input
                    className={ className('input') }
                    name="hours"
                    type="number"
                    placeholder="--"
                    min={ 0 }
                    max={ 23 }
                    value={ formatTime(props.value.hours) }
                    onKeyDown={ handleKeyDown }
                    onKeyUp={ handleKeyUp }
                    onChange={ handleChange }
                    onBlur={ handleBlur }
                    onFocus={ handleFocus }
                    disabled={props.disabled}
                />
            :
                <input
                    className={ className('input') }
                    name="minutes"
                    type="number"
                    placeholder="--"
                    min={ 0 }
                    max={ 59 }
                    value={ formatTime(props.value.minutes) }
                    onKeyDown={ handleKeyDown }
                    onKeyUp={ handleKeyUp }
                    onChange={ handleChange }
                    onBlur={ handleBlur }
                    onFocus={ handleFocus }
                    disabled={props.disabled}
                />
            </div>
            { props.after && (
                <div className={ className('after') }>
                    { props.after }
                </div>
            ) }
        </div>
    );
}));

TimePicker.defaultProps = {
    size:   'lg',
    margin: 'xs',
    after:  <Icon name="clock" />,
    disabled: false,
};
