import type { CSSProperties } from "react";
import { useEffect, useState } from "react";

export interface VisualViewportFrame {
  readonly height: number;
  readonly offsetTop: number;
}

const readVisualViewport = (): VisualViewportFrame => ({
  height: Math.round(window.visualViewport?.height ?? window.innerHeight),
  offsetTop: Math.round(window.visualViewport?.offsetTop ?? 0),
});

export const visualViewportStyle = (
  frame?: VisualViewportFrame
): CSSProperties => ({
  height: frame ? `${frame.height}px` : "100dvh",
  transform: frame?.offsetTop ? `translateY(${frame.offsetTop}px)` : undefined,
});

export const useVisualViewportStyle = (): CSSProperties => {
  const [frame, setFrame] = useState<VisualViewportFrame>();

  useEffect(() => {
    const root = document.documentElement;
    const viewport = window.visualViewport;
    let animationFrame = 0;

    const update = () => {
      cancelAnimationFrame(animationFrame);
      animationFrame = requestAnimationFrame(() => {
        setFrame(readVisualViewport());
      });
    };

    root.classList.add("workspace-viewport-lock");
    update();
    window.addEventListener("resize", update);
    viewport?.addEventListener("resize", update);
    viewport?.addEventListener("scroll", update);

    return () => {
      cancelAnimationFrame(animationFrame);
      root.classList.remove("workspace-viewport-lock");
      window.removeEventListener("resize", update);
      viewport?.removeEventListener("resize", update);
      viewport?.removeEventListener("scroll", update);
    };
  }, []);

  return visualViewportStyle(frame);
};
