'use strict';

import React from 'react';
import validator from 'validator';
import {ButtonGroup} from 'react-bootstrap';
import classnames from 'classnames';
import {FormControl, FormControlProps} from './FormControl';
import {TextInputControl} from './TextInputControl';
import {KeyCodes} from '../../../utils/constants';
import {Button} from '../Button';
import {Icon} from '../Icon';
import lang from '../../../lang/common/index-en_US';

interface InputCounterControlProps extends FormControlProps {
    maxLength: number;
    minValue: number;
    maxValue: number;
    decreaseLabel: string;
    increaseLabel: string;
    isInvalid: boolean;
}

const Natural_Number_Regex = /^[0-9]+$/;
const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991;

export class InputCounterControl extends FormControl<InputCounterControlProps> {
    static defaultProps = {
        ...FormControl.defaultProps,
        testAutomationId: 'inputCounter',
        maxLength: String(MAX_SAFE_INTEGER).length,
        minValue: 0,
        maxValue: MAX_SAFE_INTEGER,
        isInvalid: false,
        get decreaseLabel() {
            return lang.DECREASE;
        },
        get increaseLabel() {
            return lang.INCREASE;
        }
    };

    inputRef = React.createRef<TextInputControl>();

    getValue(): number | void {
        const input: TextInputControl = this.inputRef.current;

        if (input) {
            return input.getValue();
        }
    }

    setValue(value) {
        const {...props} = this.getPropsFromContext();

        props.onChange(this.getValidatedValue(value) as any);
    }

    getInputDOMNode(): void | Element {
        const input: TextInputControl = this.inputRef.current;

        if (input) {
            return input.getInputDOMNode();
        }
    }

    getValidatedValue(value): void | number {
        let minValue = this.props.minValue;
        let maxValue = this.props.maxValue;

        let isValid = validator.isInt(value, {
            min: minValue,
            max: maxValue
        });

        if (isValid) {
            return parseInt(value);
        }

        if (value < minValue || value === '') {
            return minValue;
        }

        if (value > maxValue) {
            return maxValue;
        }
    }

    onTextInputChange(e) {
        let value = e.target.value;
        const isNaturalNumber = Natural_Number_Regex.test(value);

        if (isNaturalNumber || value === '') {
            if (isNaturalNumber) {
                value = parseInt(value, 10);
            }

            this.setValue(value);
        }
    }

    onTextInputBlur() {
        this.setValue(this.getValue());
    }

    onTextInputKeyDown = e => {
        if (e.keyCode === KeyCodes.ARROW_UP || e.keyCode === KeyCodes.ARROW_DOWN) {
            if (e.keyCode === KeyCodes.ARROW_UP) {
                this.increment();
            } else {
                this.decrement();
            }
            e.preventDefault();
        }
        e.stopPropagation();
    };

    increment() {
        this.setValue(Number(this.getValue()) + 1);
    }

    decrement() {
        this.setValue(Number(this.getValue()) - 1);
    }

    render() {
        let {
            testAutomationId,
            decreaseLabel,
            increaseLabel,
            isInvalid,
            ...props
        } = this.getPropsFromContext();

        const className = classnames('input-counter', {'not-valid': isInvalid});

        return (
            <ButtonGroup
                className={className}
                data-test-automation-id={
                    this.props.hasFormGroupContainer ? undefined : testAutomationId
                }>
                <Button
                    testAutomationId="decrementButton"
                    className="decrement-button"
                    onClick={this.decrement.bind(this)}
                    aria-label={decreaseLabel}
                    tabIndex={-1}
                    disabled={props.disabled || props.value <= this.props.minValue}>
                    <Icon name="checkbox-mix-readonly" />
                </Button>
                <TextInputControl
                    {...props}
                    className="value"
                    ref={this.inputRef}
                    role="spinbutton"
                    aria-valuenow={props.value}
                    aria-valuemin={props.minValue}
                    aria-valuemax={props.maxValue}
                    min={props.minValue}
                    max={props.maxValue}
                    onChange={this.onTextInputChange.bind(this)}
                    onKeyDown={this.onTextInputKeyDown}
                    onBlur={this.onTextInputBlur.bind(this)}
                />
                <Button
                    testAutomationId="incrementButton"
                    className="increment-button"
                    onClick={this.increment.bind(this)}
                    aria-label={increaseLabel}
                    tabIndex={-1}
                    disabled={props.disabled || props.value >= this.props.maxValue}>
                    <Icon name="add-big" />
                </Button>
            </ButtonGroup>
        );
    }
}
