import {Component, FocusEvent, ChangeEvent, KeyboardEvent} from 'react'
import {Input, InputProps} from '@befe/brick-comp-input'
import {StateOperation} from '@befe/brick-utils'
import {Icon} from '@befe/brick-comp-icon'
import {FeatureCustomInput} from './create-custom-input'
import {
    PartialInputProps,
    PartialTimePickerIconProps,
} from './create-time-picker'
import {InputCloseableIcon} from './partial-input-closable-icon'

interface TimeUserInputProps extends PartialTimePickerIconProps,
    PartialInputProps {
    value: string
    onChange: (value: string) => void
    clearable: boolean
    onFocus?: (e: FocusEvent) => void
    onBlur?: (e: FocusEvent) => void
    stateUserInput?: StateOperation<boolean>
    stateOpen?: StateOperation<boolean>
    refInput?: (node: Input | null) => void
    size?: InputProps['size']
}

interface TimeUserInputState {
    userInputText: string
    hasFocus: boolean
    isHover: boolean
}


/**
 */
export class TimeUserInput extends Component<TimeUserInputProps,
    TimeUserInputState> {

    state: TimeUserInputState = {
        userInputText: '',
        hasFocus: false,
        isHover: false,
    }

    featureCustomInput = new FeatureCustomInput(this,
        {
            customValue: 'userInputText',
            hasFocus: 'hasFocus',
        },
        {
            getValue: () => this.props.value,
            onValueChange: (value) => this.props.onChange(value),
        }
    )

    closableIcon = new InputCloseableIcon(this, {
        hasValue: () => !!this.props.value,
        isFocus: () => this.state.hasFocus,
        hoverState: 'isHover',

        onClear: () => {
            this.props.onChange('')
            this.setState({
                userInputText: '',
            })
        },

        renderNode: () => this.renderIcon(),

        isClearable: () => Boolean(this.props.clearable),
        isDisabled: () => Boolean(this.props.disabled),
    })

    private readonly handleChange = (e: ChangeEvent<HTMLInputElement>) => {
        const {
            change,
        } = this.featureCustomInput.hooks

        const {
            stateUserInput,
        } = this.props;

        if (!stateUserInput?.get()) {
            stateUserInput?.set(true);
        }
        change(e);
    }

    private readonly handleFocus = (e: FocusEvent) => {
        const {onFocus, stateUserInput} = this.props
        onFocus && onFocus(e)
        stateUserInput?.set(true)
        this.featureCustomInput.hooks.focus()
    }

    private readonly handleBlur = (e: FocusEvent) => {
        this.props.stateUserInput?.set(false)
        this.featureCustomInput.hooks.blur()

        const onBlur = this.props.onBlur
        onBlur && onBlur(e)
    }

    private readonly handleIconClick = () => {
        const props = this.props
        if (props.disabled) {
            return
        }
        props.stateOpen && props.stateOpen.set(true)
    }

    private readonly handleKeyDown = (e: KeyboardEvent) => {
        const code = e.nativeEvent.code;
        if (code === 'Tab' || code === 'Enter') {
            this.props.stateUserInput?.set(false);
            this.props.stateOpen?.set(false);
            this.featureCustomInput.hooks.blur();
        }
    }

    render() {
        const iconHooks = this.closableIcon.hooks
        const props = this.props
        return (
            <Input
                ref={props.refInput}
                value={this.featureCustomInput.getValue()}
                placeholder={props.placeholder}
                size={props.size}
                status={props.status}
                suffix={this.closableIcon.render()}
                onFocus={this.handleFocus}
                onBlur={this.handleBlur}
                onChange={this.handleChange}
                onKeyDown={this.handleKeyDown}
                onMouseEnter={iconHooks.mouseEnter}
                onMouseLeave={iconHooks.mouseLeave}
                disabled={props.disabled}
            />
        )
    }

    private renderIcon() {
        const {iconSvg, iconNode} = this.props

        if (iconSvg) {
            return (
                <Icon
                    onClick={this.handleIconClick}
                    svg={iconSvg}
                />
            )
        } else if (iconNode) {
            return (
                <span onClick={this.handleIconClick}>
                    {iconNode}
                </span>
            )
        }
        return null
    }
}

