import {
  createEffect,
  createRenderEffect,
  onCleanup,
  onMount,
  type ParentComponent,
} from "solid-js";
import styles from "./BottomSheet.module.css";
import { useHeroSignal } from "../platform/anim";

export type BottomSheetProps = {
  open?: boolean;
};

export const HERO = Symbol("BottomSheet Hero Symbol");

function composeAnimationFrame({
  top,
  left,
  height,
  width,
}: Record<"top" | "left" | "height" | "width", number>) {
  return {
    top: `${top}px`,
    left: `${left}px`,
    height: `${height}px`,
    width: `${width}px`,
  };
}

const MOVE_SPEED = 1400; // 1400px/s, bottom sheet is big and a bit heavier than small papers

const BottomSheet: ParentComponent<BottomSheetProps> = (props) => {
  let element: HTMLDialogElement;
  let animation: Animation | undefined;
  const hero = useHeroSignal(HERO);

  createEffect(() => {
    if (props.open) {
      if (!element.open) {
        element.showModal();
        animateOpen();
      }
    } else {
      if (element.open) {
        if (animation) {
          animation.cancel();
        }
        element.close();
      }
    }
  });

  const animateOpen = () => {
    // Do hero animation
    const startRect = hero();
    console.debug("capture hero source", startRect);
    if (!startRect) return;
    const endRect = element.getBoundingClientRect();
    const easing = "ease-in-out";
    console.debug("easing", easing);
    element.classList.add(styles.animated);
    const distance = Math.sqrt(
      Math.pow(Math.abs(startRect.top - endRect.top), 2) +
        Math.pow(Math.abs(startRect.left - startRect.top), 2),
    );
    const duration = (distance / MOVE_SPEED) * 1000;
    animation = element.animate(
      [composeAnimationFrame(startRect), composeAnimationFrame(endRect)],
      { easing, duration },
    );
    const onAnimationEnd = () => {
      element.classList.remove(styles.animated);
      animation = undefined;
    };
    animation.addEventListener("finish", onAnimationEnd);
    animation.addEventListener("cancel", onAnimationEnd);
  };

  onCleanup(() => {
    if (animation) {
      animation.cancel();
    }
  });

  return (
    <dialog class={styles.bottomSheet} ref={element!}>
      {props.children}
    </dialog>
  );
};

export default BottomSheet;
