import { useRouter } from 'next/router';
import { useEffect } from 'react';

import { useProgressBar } from './useProgressBar';

// https://github.com/twbs/bootstrap/blob/v5.3.0-alpha1/scss/_variables.scss#L1529
const transitionSpeed = 600;

// https://gist.github.com/tkrotoff/db8a8106cc93ae797ea968d78ea28047
// https://stackoverflow.com/q/60755316
// https://stackoverflow.com/q/55624695
export function RouterProgressBar(props?: Parameters<typeof useProgressBar>[0]) {
  const { events } = useRouter();

  const { width, start, complete, reset } = useProgressBar({ transitionSpeed, ...props });

  useEffect(() => {
    events.on('routeChangeStart', start);
    events.on('routeChangeComplete', complete);
    events.on('routeChangeError', reset); // Typical case: "Route Cancelled"

    return () => {
      events.off('routeChangeStart', start);
      events.off('routeChangeComplete', complete);
      events.off('routeChangeError', reset);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  return width > 0 ? (
    <div
      className="progress fixed-top bg-transparent rounded-0"
      style={{
        height: 3, // GitHub turbo-progress-bar height is 3px
        zIndex: 1091 // $zindex-toast + 1 => always visible
      }}
    >
      <div
        className="progress-bar"
        style={{
          width: `${width}%`,
          //transition: 'none',
          // https://github.com/twbs/bootstrap/blob/v5.3.0-alpha1/scss/_variables.scss#L1529
          transition: `width ${
            // Why transition is 0 if width < 1% ?
            // If a `complete()` (width 100%) has been aborted (by a `start()`),
            // the slow CSS transition will prevent the progress bar from visually reaching width 1%
            // Without this hack (i.e. forcing the stop of the previous CSS transition),
            // the progress bar would temporary look like K 2000 (Knight Rider) car front-mounted scanner
            width > 1 ? transitionSpeed : 0
          }ms ease`
        }}
      />
    </div>
  ) : null;
}