import { OptionContext } from "@/mainview/scripts/contexts";
import { Shortcut, useShortcuts } from "@/mainview/scripts/shortcuts";
import { Direction, FocusContext, useFocusable } from "@noriginmedia/norigin-spatial-navigation";
import classNames from "classnames";
import { JSX, useContext, useEffect, useMemo, useState } from "react";
import { twMerge } from "tailwind-merge";

export function useOptionContext (params?: { onOptionEnterPress?: () => void; })
{
    const context = useContext(OptionContext);
    useEffect(() =>
    {
        if (params?.onOptionEnterPress)
        {
            context.eventTarget.addEventListener(
                "onEnterPress",
                params.onOptionEnterPress,
            );
        }

        return () =>
        {
            if (params?.onOptionEnterPress)
            {
                context.eventTarget.removeEventListener(
                    "onEnterPress",
                    params.onOptionEnterPress,
                );
            }
        };
    }, [context.eventTarget]);
    return context;
}

export function OptionSpace (data: {
    id?: string;
    className?: string;
    innerClassName?: string;
    focusable?: boolean;
    children?: any | any[];
    label?: string | JSX.Element | ((focused: boolean) => JSX.Element);
    saveLastFocusedChild?: boolean;
    preferredChildFocusKey?: string;
    shortcuts?: Shortcut[];
})
{
    const [focusBoundary, setFocusBoundary] = useState(false);
    const [focusBoundaryDirections, setFocusBoundaryDirections] = useState<Direction[]>([]);
    const eventTarget = useMemo(() => new EventTarget(), []);
    const { ref, focused, focusSelf, focusKey } = useFocusable({
        focusKey: data.id,
        focusable: data.focusable !== false,
        trackChildren: true,
        saveLastFocusedChild: data.saveLastFocusedChild ?? false,
        isFocusBoundary: focusBoundary,
        focusBoundaryDirections,
        preferredChildFocusKey: data.preferredChildFocusKey,
        onFocus ()
        {
            (ref.current as HTMLElement).scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        },
        onEnterPress ()
        {
            eventTarget.dispatchEvent(new CustomEvent("onEnterPress"));
        },
    });
    useShortcuts(focusKey, () => data.shortcuts ?? []);
    let labelElement: any = data.label;
    if (data.label instanceof Function)
    {
        labelElement = data.label(focused);
    } else if (typeof data.label === 'string')
    {
        labelElement = <label
            className={classNames({
                "font-semibold": focused,
            })}
        >
            {data.label}
        </label>;
    }

    return (<FocusContext value={focusKey}>
        <OptionContext value={{ focused, focus: focusSelf, setFocusBoundary, setFocusBoundaryDirections, eventTarget }}>
            <li
                ref={ref}
                className={twMerge("flex portrait:flex-col portrait:gap-2 portrait:p-4 md:flex-row sm:p-2 md:p-4 md:pl-8! rounded-3xl border-b border-base-content/5 focused:bg-base-300 focused-child:bg-base-300",
                    data.className,
                )}
            >
                {!!labelElement && <div className="flex gap-2 items-center flex-1 md:text-lg pr-4">
                    {labelElement}
                </div>}
                <div className={twMerge("flex flex-1 justify-end-safe", data.innerClassName)}>
                    {data.children}
                </div>
            </li>
        </OptionContext>
    </FocusContext>
    );
}