import { Interval } from "luxon";
import { RelativeRange, TimePickerRange, AppTimeRanges } from "utils";
import { useState, useRef } from "react";

interface AppTimeRangesState {
  queryRange: Interval;
  timePickerRange: TimePickerRange;
}

export function useAppTimeRanges(): AppTimeRanges {
  const [state, setState] = useState<AppTimeRangesState>(getDefaultState);

  // Create an AppTimeRanges object from the state.
  // Only recreate the AppTimeRanges object when the state object changes.
  const appTimeRangeRef = useRef<AppTimeRanges | null>(null);
  const prevStateRef = useRef<AppTimeRangesState | null>(null);
  if (prevStateRef.current !== state) {
    prevStateRef.current = state;

    appTimeRangeRef.current = {
      ...state,

      refreshQueryRange: function () {
        const queryRange = getQueryRange(state.timePickerRange);
        setState({
          ...state,
          queryRange,
        });
      },

      setTimePickerRange: function (timePickerRange: TimePickerRange) {
        const queryRange = getQueryRange(timePickerRange);
        setState({
          queryRange,
          timePickerRange,
        });
      },
    };
  }

  if (!appTimeRangeRef.current) {
    // This should never happen, but the Typescript compiler isn't clever enough to know
    // that appTimeRangeRef.current isn't null.
    throw new Error("assertion fail - appTimeRangeRef.current was null");
  }

  return appTimeRangeRef.current;
}

function getDefaultState(): AppTimeRangesState {
  const timePickerRange: TimePickerRange = TimePickerRange.fromRelative(
    RelativeRange.Last30Min
  );
  const queryRange = getQueryRange(timePickerRange);
  return {
    queryRange,
    timePickerRange,
  };
}

function getQueryRange(timePickerRange: TimePickerRange): Interval {
  if (timePickerRange.absolute) {
    return timePickerRange.absolute;
  }

  if (timePickerRange.relativeID) {
    return RelativeRange.relativeRangeToAbsolute(timePickerRange.relativeID);
  }

  throw new Error("timePickerRange is empty");
}
