/**
 * Input with color picker
 *
 * @author Dmitry Shelabin
 * @date 2022-03-14
 */

import * as React from 'react';
import {safeInvoke} from '../../utils/safeInvoke';
import * as styles from './input.m.scss';
import {Input} from './Input';
import {ColorPicker} from '../color_picker/ColorPicker';
import {ColorResult} from 'react-color';
import {Icon} from '../icon/Icon';

export type InputColorPickerProps = {
    allowClear?: boolean;
    errorMessage?: React.ReactNode;
    isReadOnly?: boolean;
    isDisabled?: boolean;
    placeholder?: string;
    color?: string;
    onChange?: (color: string) => void;
}

interface IState {
    isOpen: boolean;
    color: string;
}

export class InputColorPicker extends React.Component<InputColorPickerProps, IState> {
    constructor (props: InputColorPickerProps) {
        super(props);

        this.state = {
            color: props.color || '',
            isOpen: false
        };
    }

    prefixRef = React.createRef<HTMLDivElement>();

    override componentDidUpdate (prevProps: Readonly<InputColorPickerProps>, prevState: Readonly<IState>, snapshot?: any) {
        if (this.props.color !== prevProps.color) {
            this.setState({color: this.props.color || ''});
        }
    }

    onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        if (e.type === 'blur') {
            e.stopPropagation();
            e.preventDefault();

            return;
        }

        const color = e.currentTarget.value;

        if (!color) {
            this.onChange();
        }
    }

    onVisibleChange = (visible: boolean) => {
        this.setState({isOpen: visible});
    }

    onChange = (color?: ColorResult) => {
        const {isReadOnly, isDisabled} = this.props,
            colorHex = color ? color.hex : '';

        if (!isReadOnly && !isDisabled) {
            this.setState({color: colorHex});
            safeInvoke(this.props.onChange, colorHex);
        }
    }

    override render () {
        const {color, isOpen} = this.state;
        const {allowClear, errorMessage, isReadOnly, isDisabled, placeholder} = this.props;
        const contrastingColor = ColorPicker.getContrastingColor(ColorPicker.hexToRGB(color));

        return (
            <ColorPicker
                colorHex={color}
                onColorChange={this.onChange}
                isOpen={isOpen}
                onClose={(e: React.SyntheticEvent<Element> | Event) => {
                    const prefixEl = this.prefixRef.current,
                        onPrefixClick = prefixEl && prefixEl.contains(e.target as Node);

                    this.onVisibleChange(false);

                    if (onPrefixClick) {
                        e.stopPropagation();
                    }
                }}

                target={(
                    <div>
                        <Input
                            value={color}
                            onChange={this.onInputChange}
                            onPrefixClick={() => !isReadOnly && !isDisabled && !isOpen && this.onVisibleChange(true)}
                            allowClear={allowClear && !isReadOnly && !isDisabled}
                            hasError={Boolean(errorMessage)}
                            errorMessage={errorMessage}
                            readOnly={isReadOnly}
                            isDisabled={isDisabled}
                            prefix={(
                                <div
                                    style={color ? {backgroundColor: color} : undefined}
                                    className={styles.colorInputPrefix}
                                    ref={this.prefixRef}>
                                    <Icon
                                        name={'pencil-line'}
                                        style={color ? {fill: contrastingColor} : undefined}/>
                                </div>
                            )}
                            placeholder={placeholder}
                        />
                    </div>
                )}/>
        );
    }
}
