import React, { useRef, InputHTMLAttributes, useImperativeHandle, useState, useContext, MutableRefObject } from 'react';
import { useEventListener } from '@devesharp/react-hooks';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import AppContext from '../AppProvider/AppContext';
import { LoaderIcon } from '../LoaderIcon';
import { maskValue } from '../MaskText/mask.utils';
import { FormStyle } from '../styles';
import Style from './Input.style';
import { InputCore } from './InputCore';
import { IInputProps } from './InputCore.interface';

export const InputPure = React.forwardRef<InputHTMLAttributes<any>, IInputProps>(function InputPure(
   props,
   inputRef: any,
) {
   const {
      title,
      color,
      error,
      textRight,
      textCenter,
      defaultValue,
      loading,
      prefix,
      onEnter,
      password,
      value: valueInput,
      suffix,
      withoutDotNumber,
      as /**/,
      ...rest
   } = props;
   // ref component
   const ref = useRef<HTMLInputElement>();
   useImperativeHandle(inputRef, () => ref.current, []);

   // focus
   const [focus, setFocus] = useState(false);

   // mask in value
   let value;
   if (valueInput != undefined) {
      value = maskValue(props.value, props.mask, props as any);
   }

   // onEnter
   useEventListener('keydown.enter', () => onEnter && onEnter(ref.current.value), inputRef);

   const [hidePassword, setHidePassword] = useState(true);

   // class
   const className = ['input-border'];
   if (textRight) className.push('text-right');
   if (rest?.type === 'hidden') className.push('input-hidden');
   if (error) className.push('has-error');
   if (focus) className.push('focus');

   /**
    * Custom component
    */
   const context = useContext(AppContext);
   const CustomInputComponent = context?.customComponents?.Input;

   if (props.CustomComponent || CustomInputComponent) {
      const { CustomComponent = CustomInputComponent } = props;
      return (
         <CustomComponent
            inputProps={{
               ref,
               defaultValue: value ? undefined : maskValue(defaultValue, props.mask, props as any),
               type: hidePassword && password ? 'password' : 'text',
               value,
               ...(rest as any),
               onBlur: (ev) => {
                  if (rest.onBlur) rest.onBlur(ev);
                  setFocus(false);
               },
               onFocus: (ev) => {
                  if (rest.onFocus) rest.onFocus(ev);
                  setFocus(true);
               },
               onInput: (evt) => {
                  if (rest.onInput) rest.onInput((evt.target as any).value);
               },
            }}
            title={title}
            prefix={prefix}
            suffix={suffix}
            error={error}
            focus={focus}
            loading={loading}
            password={password}
            textCenter={textCenter}
            hidePassword={hidePassword}
            setHidePassword={setHidePassword}
         />
      );
   }
   return (
      <FormStyle className="input-container">
         <Style>
            {title && <div className={`input-title ${focus && 'focus'}`}>{title}</div>}

            <div className={className.join(' ')}>
               {prefix && <div className="prefix">{prefix}</div>}
               <input
                  ref={ref}
                  defaultValue={value ? undefined : maskValue(defaultValue, props.mask, props as any)}
                  type={hidePassword && password ? 'password' : 'text'}
                  {...(rest as any)}
                  value={value}
                  autoComplete="off"
                  onBlur={(ev) => {
                     ref.current?.removeAttribute('autocomplete');
                     if (rest.onBlur) rest.onBlur(ev);
                     setFocus(false);
                  }}
                  onFocus={(ev) => {
                     ref.current?.setAttribute('autocomplete', 'chrome-off');
                     if (rest.onFocus) rest.onFocus(ev);
                     setFocus(true);
                  }}
                  onInput={(evt) => {
                     if (rest.onInput) rest.onInput((evt.target as any).value);
                  }}
                  className={`${textCenter && ' text-center'}`}
               />
               {loading && (
                  <div className="suffix suffix-loading">
                     <LoaderIcon size={18} />
                  </div>
               )}
               {suffix && <div className="suffix">{suffix}</div>}
               {password && <ViewPasswordToggle hidePassword={hidePassword} setHidePassword={setHidePassword} />}
            </div>

            {error && (
               <div className="error-input" data-testid="input-error">
                  {error}
               </div>
            )}
         </Style>
      </FormStyle>
   );
});

export function ViewPasswordToggle({ hidePassword, setHidePassword }): JSX.Element {
   return (
      <div className="suffix password-btn" onClick={() => setHidePassword(!hidePassword)}>
         {hidePassword && <FontAwesomeIcon icon={faEyeSlash} />}
         {!hidePassword && <FontAwesomeIcon icon={faEye} />}
      </div>
   );
}

export const Input = React.forwardRef<InputHTMLAttributes<any>, IInputProps>(function Checkbox(props, inputRef: any) {
   const ref = useRef<any>();

   useImperativeHandle(inputRef, () => ref.current, []);

   useEventListener(
      'input',
      () => {
         if (ref.current) {
            ref.current.value = maskValue(ref.current?.value, props.mask, props as any);
         }
      },
      ref,
   );

   return <InputCore {...props} ref={ref} as={InputPure} />;
});
