import React, { useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { Icon } from 'common/components/icon';
import { IconName } from 'common/components/icon/types';
import { Widget } from 'common/constants';
import { bem } from 'utils/bem';
import { BgStyle } from 'common/styles/utils';
import { SInputWrapper } from './s-input';

interface Props {
  placeholder?: string;
  value?: string;
  initialValue?: string;
  className?: string;
  iconLeft?: IconName;
  bgStyle?: BgStyle;
  clearable?: boolean;
  disabled?: boolean;
  readonly?: boolean;
  dataSelector?: string;
  maxLength?: number;
  autoFocus?: boolean;
  isRequired?: boolean;
  isInvalid?: boolean;
  onChange(value?: string): void;
  onBlur?(): void;
  onPressEnter?(): void;
  onFocus?(): void;
  onMouseDown?(event): void;
}

const classes = bem('input');

export const Input = React.memo(
  React.forwardRef(
    (
      {
        placeholder,
        value = '',
        initialValue = '',
        className,
        iconLeft,
        bgStyle = 'white',
        clearable = false,
        disabled = false,
        readonly = false,
        isRequired = false,
        isInvalid = false,
        dataSelector,
        maxLength,
        onChange,
        onBlur,
        onPressEnter,
        onFocus,
        autoFocus,
        onMouseDown,
      }: Props,
      forwardRef
    ) => {
      const inputRef = useRef<HTMLInputElement>(null);

      const [inputValue, setInputValue] = useState(initialValue);

      const onChangeHandler = useCallback(
        ({ target: { value } }: React.ChangeEvent<HTMLInputElement>) => {
          setInputValue(value);
          onChange(value);
        },
        [onChange]
      );

      const onKeyUpHandler = useCallback(() => onPressEnter?.(), [onPressEnter]);

      const clearInput = useCallback(() => {
        setInputValue('');
        onChange('');
      }, [onChange]);

      useEffect(() => setInputValue(value), [value]);

      useImperativeHandle(forwardRef, () => inputRef.current);

      return (
        <SInputWrapper
          className={className}
          bgStyle={bgStyle}
          hasIconLeft={!!iconLeft}
          disabled={disabled}
          isRequired={isRequired}
          isInvalid={isInvalid}
        >
          <div className={classes('wrapper')}>
            {iconLeft && (
              <Icon size="general" name={iconLeft} className={classes('icon', { left: true })} dataSelector="search" />
            )}
            <input
              ref={inputRef}
              value={inputValue}
              autoFocus={autoFocus}
              type={Widget.Text}
              placeholder={placeholder}
              disabled={disabled}
              readOnly={readonly}
              data-selector={dataSelector}
              maxLength={maxLength}
              onChange={onChangeHandler}
              onBlur={onBlur}
              onKeyUp={onKeyUpHandler}
              onFocus={onFocus}
              onMouseDown={onMouseDown}
            />
            {clearable && inputValue && (
              <Icon
                name="removal"
                size="general"
                className={classes('close', { right: true })}
                onClick={clearInput}
                dataSelector="remove"
              />
            )}
          </div>
        </SInputWrapper>
      );
    }
  )
);
