import rafSchd from "raf-schd";
import scroll from "./scroll";
import { invariant } from "../../../invariant";
import * as timings from "../../../debug/timings";

const fluidScroller = ({ scrollWindow, scrollDroppable }) => {
  const scheduleWindowScroll = rafSchd(scrollWindow);
  const scheduleDroppableScroll = rafSchd(scrollDroppable);
  let dragging = null;
  const tryScroll = (state) => {
    invariant(dragging, "Cannot fluid scroll if not dragging");
    const { shouldUseTimeDampening, dragStartTime } = dragging;
    scroll({
      state,
      scrollWindow: scheduleWindowScroll,
      scrollDroppable: scheduleDroppableScroll,
      dragStartTime,
      shouldUseTimeDampening
    });
  };
  const start = (state) => {
    timings.start("starting fluid scroller");
    invariant(!dragging, "Cannot start auto scrolling when already started");
    const dragStartTime = Date.now();
    let wasScrollNeeded = false;
    const fakeScrollCallback = () => {
      wasScrollNeeded = true;
    };
    scroll({
      state,
      dragStartTime: 0,
      shouldUseTimeDampening: false,
      scrollWindow: fakeScrollCallback,
      scrollDroppable: fakeScrollCallback
    });
    dragging = {
      dragStartTime,
      shouldUseTimeDampening: wasScrollNeeded
    };
    timings.finish("starting fluid scroller");

    // we know an auto scroll is needed - let's do it!
    if (wasScrollNeeded) {
      tryScroll(state);
    }
  };
  const stop = () => {
    // can be called defensively
    if (!dragging) {
      return;
    }
    scheduleWindowScroll.cancel();
    scheduleDroppableScroll.cancel();
    dragging = null;
  };
  return {
    start,
    stop,
    scroll: tryScroll
  };
};

export default fluidScroller;
