import { ArrowsPointingInIcon, ArrowsPointingOutIcon } from "@heroicons/react/24/solid";
import { type MouseEvent, type ReactElement, useEffect, useRef, useState } from "react";
import { getSpacingClass, type SpacingVariants } from "../style/Spacing.js";
import { getWidthClass, type WidthVariants } from "../style/Width.js";
import { getClass, getModuleClass } from "../util/css.js";
import type { ChildProps, OptionalChildProps } from "../util/props.js";
import styles from "./Video.module.css";

export interface VideoProps extends SpacingVariants, WidthVariants, OptionalChildProps {}

export interface VideoButtonsProps extends ChildProps {
	left?: boolean;
}

export interface VideoButtonProps extends ChildProps {
	title?: string | undefined;
	onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
	danger?: boolean;
	disabled?: boolean;
}

/**
 * Video container element.
 * - Has a black background and a 16:9 aspect ratio.
 * - Shows its contents (i.e. a `<video>` element or a `<TwilioRoom>`.
 */
export function Video({ children, ...variants }: VideoProps): ReactElement {
	const ref = useRef<HTMLElement | null>(null);

	return (
		<figure ref={ref} className={getClass(getModuleClass(styles, "video"), getSpacingClass(variants), getWidthClass(variants))}>
			{children}
		</figure>
	);
}

/** Set of video buttons floating over a video. */
export function VideoButtons({ children, ...variants }: VideoButtonsProps) {
	return <div className={getModuleClass(styles, "buttons", variants)}>{children}</div>;
}

/** Individual video button over a video. */
export function VideoButton({ children, title, onClick, disabled, ...variants }: VideoButtonProps): ReactElement {
	return (
		<button type="button" onClick={onClick} className={getModuleClass(styles, "button", variants)} title={title} disabled={disabled}>
			{children}
		</button>
	);
}

declare const _fullscreenVideoButtonProps: unique symbol;

export interface FullscreenVideoButtonProps {
	readonly [_fullscreenVideoButtonProps]?: never;
}

/** Button to make a video element go fullscreen. */
export function FullscreenVideoButton(): ReactElement | null {
	const [isFull, setFull] = useState(() => typeof document !== "undefined" && !!document.fullscreenElement);

	useEffect(() => {
		const onChange = () => setFull(!!document.fullscreenElement);
		document.addEventListener("fullscreenchange", onChange);
		return () => document.removeEventListener("fullscreenchange", onChange);
	});

	if (!document.fullscreenEnabled) return null;

	return (
		<VideoButton
			title={isFull ? "Exit full screen mode" : "Enter full screen mode"}
			onClick={({ currentTarget }) => {
				if (document.fullscreenElement) {
					document.exitFullscreen();
				} else {
					const parent = currentTarget.closest("figure, video");
					if (parent) parent.requestFullscreen();
				}
			}}
		>
			{isFull ? <ArrowsPointingInIcon /> : <ArrowsPointingOutIcon />}
		</VideoButton>
	);
}
