import type { History } from 'history';
import { ContextType, useContext } from 'react';
import {
  Navigator as BaseNavigator,
  UNSAFE_NavigationContext as NavigationContext,
} from 'react-router-dom';
import { useFormikContext } from 'formik';
import LegacyFormBasedPreventNavigation from './LegacyFormBasedPreventNavigation';
import NewFormBasedPreventNavigation from './NewFormBasedPreventNavigation';

interface Navigator extends BaseNavigator {
  block?: History['block'];
  location: Location;
}

type NavigationContextWithBlock = ContextType<typeof NavigationContext> & {
  navigator: Navigator;
};

export interface FormBasedPreventNavigationProps {
  ignoreLostChanges?: boolean;
  promptMessage?: string;
}

/** Prevent the user from navigating away from a form if there are any changes. */
export default function FormBasedPreventNavigation({
  ignoreLostChanges,
  promptMessage = 'Changes you made may not be saved.',
}: FormBasedPreventNavigationProps) {
  const { dirty, isSubmitting } = useFormikContext();
  const preventNavigate = !ignoreLostChanges && dirty && !isSubmitting;

  const { navigator } = useContext(
    NavigationContext
  ) as NavigationContextWithBlock;

  const isUsingDataRouter = navigator.location === undefined;

  if (isUsingDataRouter) {
    return (
      <NewFormBasedPreventNavigation
        promptMessage={promptMessage}
        preventNavigate={preventNavigate}
        navigator={navigator}
      />
    );
  } else {
    return (
      <LegacyFormBasedPreventNavigation
        promptMessage={promptMessage}
        preventNavigate={preventNavigate}
        navigator={navigator}
      />
    );
  }
}
