import {
  ChangeEvent,
  RefObject,
  useCallback,
  useEffect,
  useState,
} from 'react';

export default function useTextBox(
  value: string,
  onChange: (value: string) => void,
  ref: RefObject<HTMLInputElement | null>,
  eager = false,
) {
  const [currentValue, setCurrentValue] = useState<string | undefined>();
  const [currentValueValid, setCurrentValueValid] = useState(false);

  const set = useCallback((value: string) => setCurrentValue(value), []);
  const reset = useCallback(() => setCurrentValue(undefined), []);
  const commit = useCallback(() => {
    reset();
    if (!eager && currentValue !== undefined && currentValueValid) {
      onChange(currentValue);
    }
  }, [eager, currentValue, currentValueValid, reset, onChange]);

  const handleChange = useCallback(
    (event: ChangeEvent<HTMLInputElement>) => {
      const value = event.target.value;
      const valid = event.target.validity.valid;
      setCurrentValue(value);
      setCurrentValueValid(valid);
      if (eager && valid) {
        onChange(value);
      }
    },
    [eager, onChange]
  );
  useEffect(() => {
    const input = ref.current;
    if (input) {
      input.addEventListener('change', commit);
      return () => input.removeEventListener('change', commit);
    }
  }, [ref, commit]);

  return {
    value: currentValue ?? value,
    onChange: handleChange,
    set,
    commit,
    reset,
  };
}
