import React, { useCallback, useRef, useEffect } from "react";

import classNames from "classnames";

import Spottable from "@enact/spotlight/Spottable";

import { AUTO_SCROLL_GAP } from "../../utils/Config";
import { scaleW } from "../../utils/helperMethods";
import css from "./AutoScrollArea.module.less";
import { useSelector } from "react-redux";

const AutoScrollComponent = Spottable("div");

const POSITION = {
  left: "left",
  right: "right",
  top: "top",
  bottom: "bottom",
};

export default function AutoScrollArea({
  position,
  autoScroll,
  scrollHorizontalPos,
  scrollVerticalPos,
  scrollToRef,
  scrollPosition,
  direction,
}) {
  const requestIdRef = useRef();
  const { cursorVisible } = useSelector((state) => state.common.appStatus);

  const handleFocusAutoScroll = useCallback(() => {
    if (!autoScroll) return;

    const scrollStep =
      position === "right" || position === "bottom"
        ? scaleW(AUTO_SCROLL_GAP)
        : scaleW(-AUTO_SCROLL_GAP);

    let start = null;

    const animationScroll = (timestamp) => {
      if (!start) start = timestamp;
      const progress = timestamp - start;
      const step = Math.min(progress / 1000, 1);

      if (direction === "horizontal") {
        scrollHorizontalPos.current += scrollStep * step;
        scrollToRef.current({
          position: { x: scrollHorizontalPos.current },
          animate: false,
        });
      } else if (direction === "vertical") {
        scrollVerticalPos.current += scrollStep * step;
        scrollToRef.current({
          position: { y: scrollVerticalPos.current },
          animate: false,
        });
      }

      if (
        direction === "horizontal" &&
        ((position === "right" && scrollPosition.current === "right") ||
          (position === "left" && scrollPosition.current === "left"))
      ) {
        if (typeof window === "object") {
          window.cancelAnimationFrame(requestIdRef.current);
        }
      } else if (
        direction === "vertical" &&
        ((position === "bottom" && scrollPosition.current === "bottom") ||
          (position === "top" && scrollPosition.current === "top"))
      ) {
        if (typeof window === "object") {
          window.cancelAnimationFrame(requestIdRef.current);
        }
      } else {
        if (typeof window === "object") {
          requestIdRef.current = window.requestAnimationFrame(animationScroll);
        }
      }
    };

    if (typeof window === "object") {
      requestIdRef.current = window.requestAnimationFrame(animationScroll);
    }
  }, [
    autoScroll,
    position,
    scrollHorizontalPos,
    scrollVerticalPos,
    scrollToRef,
    scrollPosition,
    direction,
  ]);

  const handleBlur = useCallback(() => {
    if (requestIdRef.current && typeof window === "object") {
      window.cancelAnimationFrame(requestIdRef.current);
    }
  }, [autoScroll, direction]);

  useEffect(()=>{
    return ()=>{
      if (requestIdRef.current && typeof window === "object") {
        window.cancelAnimationFrame(requestIdRef.current);
      }
    }
  },[]);

  return (
    <AutoScrollComponent
      className={classNames(css.autoScrollArea, position && css[position])}
      spotlightDisabled={!cursorVisible}
      disabled={!cursorVisible}
      onFocus={handleFocusAutoScroll}
      onBlur={handleBlur}
    />
  );
}

export { POSITION };
