import { reaction } from "mobx";
import {
  DependencyList,
  useContext,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { StatusBar } from "react-native";
import { cancelAnimation, useSharedValue } from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { TContext } from "../TProvider";
import { Platform_iOS, vs } from "../commons";
import { tBaseStore } from "../store";
import { DimensionsType, MeasureFunc } from "../types";

export * from "./useOTPCode";

const STATUS_BAR_HEIGHT = StatusBar.currentHeight || 0;

export const useColors = () => {
  return useContext(TContext).theme;
};

export const useSafeArea = (withDefaultValue?: boolean) => {
  const insets = useSafeAreaInsets();
  return {
    ...insets,
    bottom: insets.bottom || (withDefaultValue ? 0 : vs(16)),
    top: Platform_iOS
      ? insets.top
      : Math.max(STATUS_BAR_HEIGHT, withDefaultValue ? 0 : vs(32)),
  };
};

export const useReanimatedValue = <T,>(value: T) => {
  const val = useSharedValue<T>(value);

  useEffect(() => {
    return () => {
      cancelAnimation(val);
    };
  }, []);

  return val;
};

export const useReaction = <T,>(
  expression: () => T,
  effect: (v: T) => void,
  deps: DependencyList = []
) => {
  const sub = useMemo(() => reaction(expression, effect), deps);

  useEffect(() => {
    return () => {
      sub();
    };
  }, deps);
};

export const useDimensions = (
  callback?: boolean | ((d: DimensionsType) => void)
) => {
  const [dimens, setDimens] = useState(tBaseStore.dimens);

  useReaction(
    () => tBaseStore.dimens,
    (d) => (typeof callback === "boolean" ? setDimens(d) : callback?.(d))
  );

  return dimens;
};

export const useMeasure = (
  duration?: number
): [any, (cb: MeasureFunc) => void] => {
  const refView = useRef<any>();
  const refTimeout = useRef<any>(0);

  const run = (callback: MeasureFunc) => {
    refView.current?.[Platform_iOS ? "measureInWindow" : "measure"](
      (x: number, y: number, w: number, h: number, pX: number, pY: number) => {
        callback({ x: Platform_iOS ? x : pX, w, h, y: Platform_iOS ? y : pY });
      }
    );
  };

  const measure = (callback: MeasureFunc) => {
    if (duration)
      refTimeout.current = setTimeout(() => {
        run(callback);
      }, duration);
    else run(callback);
  };

  useEffect(() => {
    return () => {
      refTimeout.current && clearTimeout(refTimeout.current);
    };
  }, []);

  return [refView, measure];
};

export const useModal = (): [any, () => void, () => void] => {
  const refModal = useRef<any>();

  const show = () => {
    refModal.current?.show();
  };

  const dismiss = () => {
    refModal.current?.dismiss();
  };

  return [refModal, show, dismiss];
};

export const useTab = (): [
  any,
  (i: number) => void,
  () => void,
  () => void
] => {
  const refTab = useRef<any>();

  const set = (i: number) => {
    refTab.current?.set(i);
  };

  const prev = () => {
    refTab.current?.prev();
  };

  const next = () => {
    refTab.current?.next();
  };

  return [refTab, set, prev, next];
};
