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

export const CheckBoxCore = React.forwardRef<InputHTMLAttributes<any>, ICheckboxProps>(function Checkbox(
   props,
   inputRef: any,
) {
   if (props.name) {
      return <CheckboxWithUnform {...props} ref={inputRef} />;
   }

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

export const CheckboxWithUnform = React.forwardRef<InputHTMLAttributes<any>, ICheckboxProps>(
   function CheckboxWithUnform(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) {
         clearError();
         setChecked(!!newValue);
         if (props.onChange) props.onChange(newValue);
      }, []);

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

export const CheckboxWithoutUnform = React.forwardRef<InputHTMLAttributes<any>, ICheckboxProps>(
   function CheckboxWithoutUnform(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} />;
   },
);
