import React, {
   useRef,
   useEffect,
   InputHTMLAttributes,
   useState,
   useImperativeHandle,
   useCallback,
   useMemo,
} from 'react';
import { useField } from '@unform/core';
import * as _ from 'lodash';
import { ISwitchProps } from './Switch.interface';

export const SwitchCore = React.forwardRef<InputHTMLAttributes<any>, ISwitchProps>(function Switch(
   props,
   inputRef: any,
) {
   if (props.name) {
      return <SwitchWithUnform {...props} ref={inputRef} />;
   }

   return <SwitchWithoutUnform {...props} ref={inputRef} />;
});

export const SwitchWithUnform = React.forwardRef<InputHTMLAttributes<any>, ISwitchProps>(function SwitchWithUnform(
   props,
   inputRef: any,
) {
   const { valueTrue = true, valueFalse = false } = props;
   const { fieldName, registerField, defaultValue = null, error, clearError } = useField(props.name);
   const inputValueRef = useRef(defaultValue);
   const [checked, setChecked] = useState(_.isEqual(defaultValue, valueTrue));

   useEffect(() => {
      registerField({
         name: fieldName,
         ref: inputValueRef,
         path: 'current' as any,
         clearValue(ref) {
            ref.current = valueFalse;
            setChecked(false);
         },
         setValue(ref, v) {
            ref.current = v;
            setChecked(_.isEqual(v, valueTrue));
         },
         getValue(ref) {
            return ref.current;
         },
      });
   }, [fieldName, registerField]);

   const onChange = useCallback(
      function onSelectItem(newValue: any) {
         if (error) clearError();
         setChecked(!!newValue);
         inputValueRef.current = !!newValue;

         if (props.onChange) props.onChange(newValue);
      },
      [error],
   );

   return <SwitchWithoutUnform {...props} ref={inputRef} onChange={onChange} checked={checked} error={error} />;
});

export const SwitchWithoutUnform = React.forwardRef<InputHTMLAttributes<any>, ISwitchProps>(
   function SwitchWithoutUnform(props, inputRef: any) {
      const ref = useRef(null);
      useImperativeHandle(inputRef, () => ref.current, []);

      const PureComponent = useMemo(() => props.as, [props.as]) as any;

      return <PureComponent {...props} ref={ref} />;
   },
);
