import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import debounce from 'lodash/debounce';
import PropTypes from 'prop-types';

const styles = theme => ({
    MuiTextFieldRoot: {
        width: 95,
        '& input[type=number]::-webkit-inner-spin-button': {
            '-webkit-appearance': 'none',
            margin: 0,
        },
        '& input[type=number]::-webkit-outer-spin-button': {
            '-webkit-appearance': 'none',
            margin: 0,
        },
        '& > label': {
            margin: '-8px 0',
            '&.MuiInputLabel-shrink': {
                margin: 0,
            },
            [theme.breakpoints.down('xs')]: {
                margin: 0,
            },
        },
        [theme.breakpoints.down('xs')]: {
            width: 75,
        },
        '& input': {
            height: 20,
            [theme.breakpoints.down('xs')]: {
                height: 18,
            },
        },
        '&:nth-child(even) ': {
            marginRight: 10,
        },
        [theme.breakpoints.down('xs')]: {
            marginRight: 10,
            '&:not(first-child) ': {
                marginRight: 0,
            },
        },
    },
    amountInput: {
        textAlign: 'center',
        maxWidth: 100,
        width: '100%',
        padding: '10px 0 10px',
        fontSize: '15px !important',
        color: theme.palette.primary.darkText,
        [theme.breakpoints.down('xs')]: {
            padding: '19px 0 !important',
        },
    },
});

class AmountInput extends React.Component {
    static propTypes = {
        value: PropTypes.string,
        classes: PropTypes.object,
        inputProps: PropTypes.object,
        rootProps: PropTypes.string,
        onChangeDebounceWait: PropTypes.number,
        onChange: PropTypes.func,
        onBlur: PropTypes.func,
        min: PropTypes.number,
        max: PropTypes.number,
        amountLabel: PropTypes.string,
        autoFocus: PropTypes.bool,
        error: PropTypes.bool,
        disabled: PropTypes.bool,
        onClick: PropTypes.func,
        onFocus: PropTypes.func,
        readOnly: PropTypes.bool,
        hasValueLabel: PropTypes.bool,
        type: PropTypes.string,
    };
    static defaultProps = {
        min: 0,
        max: 999999,
        onChangeDebounceWait: 700,
        hasValueLabel: false,
        type: 'text',
    };

    state = {
        value: '',
        changeInprogress: false,
    };

    componentDidMount() {
        const {
            props: { value },
        } = this;
        this.setState({ value });
    }

    componentDidUpdate(prevProps) {
        const {
            props: { value },
        } = this;
        if (prevProps.value !== value && !this.state.changeInprogress) {
            this.updateDebounced();
        }
    }

    updateDebounced = debounce(() => {
        const {
            props: { value },
        } = this;
        if (value !== this.state.value) {
            this.setState({ value });
        }
    }, 500);

    validateKey = event => {
        const regEx = /^[0-9\b]+$/;
        const keyCode = event.keyCode || event.which;
        const keyValue = String.fromCharCode(keyCode);
        if (!regEx.test(keyValue)) {
            event.preventDefault();
        }
    };

    onChangeDebounced = debounce(() => {
        this.props.onChange(this.state.value === '' ? 0 : this.state.value);
    }, this.props.onChangeDebounceWait);

    onChange = ({ target: { value: inputValue } }) => {
        const { min, max } = this.props;
        const value = !inputValue ? inputValue : Math.min(max, Math.max(min, parseInt(inputValue)));
        this.setState(
            {
                value: isNaN(value) ? '' : value,
            },
            this.onChangeDebounced
        );
    };

    onBlur = event => {
        const {
            target: { value },
        } = event;
        const { onChange, onBlur, min, hasValueLabel } = this.props;
        this.setState({ changeInprogress: false });
        if (value === '') {
            const initialValue = min;
            this.setState({ value: initialValue });
            onChange(initialValue);
        }
        if (hasValueLabel) {
            this.updateDebounced();
        }
        onBlur && onBlur(event);
    };

    onFocus = event => {
        const { onFocus } = this.props;
        this.setState({ changeInprogress: true });
        onFocus && onFocus(event);
    };

    render() {
        const {
            classes,
            amountLabel,
            min,
            max,
            autoFocus,
            error,
            disabled,
            onClick,
            readOnly,
            rootProps,
            inputProps,
            type,
        } = this.props;

        return (
            <TextField
                value={this.state.value}
                onChange={this.onChange}
                onBlur={this.onBlur}
                autoFocus={autoFocus}
                label={amountLabel}
                margin="normal"
                variant="outlined"
                onKeyPress={this.validateKey}
                onPaste={event => {
                    event.preventDefault();
                }}
                onClick={onClick}
                inputProps={{
                    className: classes.amountInput,
                    min,
                    max,
                    readOnly,
                    ...inputProps,
                }}
                classes={{ root: classes.MuiTextFieldRoot + ' ' + rootProps }}
                error={error}
                disabled={disabled}
                onFocus={this.onFocus}
                type={type}
            />
        );
    }
}

export default withStyles(styles, { name: 'AmountInput' })(AmountInput);
