import * as React from 'react';
import {debounce as db, isEmpty,} from 'lodash';
import classNames from 'classnames';
import {getId, nullToString,} from '../function';
import FormComponent from '../FormComponent';
import RenderHtml from '../renderFunction';
import PropsTypes from './types';

interface State extends PropsTypes {
    focus: boolean,
    uuid: string,
    isActiveComponent: boolean,
}

function debounceTime(debounce:number) {
    return debounce ? debounce : 0
}

export default class Input extends FormComponent<PropsTypes, State> {

    public state: State;
    private textarea = React.createRef<HTMLTextAreaElement>();

    constructor(props: PropsTypes, {}) {
        super(props);
        const uuid = getId(props.id, this.defaultId);

        this.state = {
            focus: false,
            uuid: uuid,
            value: nullToString(props.value),
            autoFocus: false,
            isActiveComponent: false
        };

        this.debounce = db(this.debounce, debounceTime(props.debounce || 0));
    }

    async componentDidMount() {
        const {autoFocus, value} = this.state;
        if (autoFocus) {
            await this.focus();
        }
        this.validate(value);
        this.props.element && this.props.element(this.textarea);
    }

    focus() {
        const {value} = this.state;
        this.textarea.current && this.textarea.current.focus();

        if (value) {
            this.debounce()
        }

        this.setState({
            focus: true,
            isActiveComponent: true
        })
    }

    debounce() {
        this.dataOnReady()
    }

    componentWillReceiveProps(nextProps: any) {
        if (nextProps.value !== this.props.value) {
            let newValue = nullToString(nextProps.value);

            this.setState({
                value: newValue
            }, () => {
                this.setInputValue()
            })
        }
    }

    dataOnReady() {
        this.props.onChange && this.props.onChange(this.getInputData()['output'])
    }

    handleChange(e: any) {
        let inputValue: string = e.target.value;

        this.setState({
            value: inputValue
        }, () => {
            this.debounce();
            this.validate(inputValue);
        })
    }

    handleBlur = () => {
        this.props.onBlur && this.props.onBlur(this.getInputData()['output']);
    };

    handleClick = () => {
        this.props.onClick && this.props.onClick()
    };

    handlePress = (e: any) => {
        this.props.onKeyPress && this.props.onKeyPress(e)
    };

    handleDown = (e: any) => {
        this.props.onKeyDown && this.props.onKeyDown(e)
    };

    setInputValue() {
        let val: any = this.getInputData()['value'];

        this.setState({
            value: val,
        }, () => {
            this.validate(val);
            this.dataOnReady()
        })
    }

    getInputData() {
        const {value} = this.state;
        let result: Object = {};
        let output: any = null;
        let str: string | undefined = value;

        output = str;

        result = {
            value: str,
            output
        };

        return result
    }

    outsideClick() {
        const {isActiveComponent} = this.state;

        if (isActiveComponent) {
            this.setState({
                focus: false,
                isActiveComponent: false,
            })
        }
    }

    public render(): JSX.Element {

        const {value, focus, uuid} = this.state;
        const {label, icon, disabled, maxLength, loading, placeholder, spellCheck, height, customStyle, caption, infoText, noBorder, noRadius} = this.props;

        const uiClass = classNames(`jump-ui-container jump-ui-textarea ${customStyle || ''}`, {
                'focus': focus,
                'icon': this.iconLeft(),
                'icon-left': this.iconLeft(),
                'icon-right': this.iconRight(),
                'error': !isEmpty(this.error()),
                'disabled': disabled,
                'readonly': this.readOnly(),
                'no-border': noBorder,
                'no-radius': noRadius,
            }),
            captionClass = classNames('caption-text-ui', {
                'data-active': value,
            });

        return (
            <div className={`${uiClass} default-ui ${this.size() ? this.size() : 'medium-ui'}`} style={{height: height}}>
                {RenderHtml.renderLabel(label, 'left')}
                {RenderHtml.renderIcon(icon, 'left')}
                <div className="form-jump-ui-container" onClick={() => this.focus()}>
                    <div className="form-ui">
                            <textarea
                                id={`input-${uuid}`}
                                name={`name-${uuid}`}
                                className="jump-ui"
                                value={value}
                                placeholder={placeholder || ''}
                                onChange={(val: any) => this.handleChange(val)}
                                onBlur={() => this.handleBlur()}
                                onClick={() => this.handleClick()}
                                onKeyPress={(e) => {this.handlePress(e)}}
                                onKeyDown={(e) => this.handleDown(e)}
                                disabled={disabled}
                                readOnly={this.readOnly()}
                                maxLength={maxLength}
                                ref={this.textarea}
                                tabIndex={0}
                                spellCheck={spellCheck ? spellCheck : false}
                            />
                    </div>
                    <div className={`${captionClass}`}>
                        {caption}
                    </div>
                </div>
                {RenderHtml.renderLoading(loading)}
                {RenderHtml.renderError(this.error())}
                {isEmpty(this.error()) ? <div className="info-text-ui">{infoText}</div> : null}
                {RenderHtml.renderIcon(icon, 'right')}
                {RenderHtml.renderLabel(label, 'right')}
            </div>
        );
    }

}
