import { ComponentChildren, Ref, RefObject } from "preact";
import { useCallback, useRef, useState } from "preact/hooks";

export function Window(props: Window.Props) {
    const windowRef: Ref<HTMLDivElement> = useRef(null);
    const dragTimeout: Ref<ReturnType<typeof setTimeout>> = useRef(null);
    
    const [x, setX] = useState(props.x ?? 0);
    const [y, setY] = useState(props.y ?? 0);

    const initialOffsetX = useRef(0);
    const initialOffsetY = useRef(0);

    const updatePosition = useCallback((e: MouseEvent) => {
        setX(e.clientX - initialOffsetX.current)
        setY(e.clientY - initialOffsetY.current)
    }, [])

    const startDrag = useCallback((e: MouseEvent) => {
        if (e.button === 0) {

            const BORDER_WIDTH = 1;
            console.log(e);
            // Naturally, I have to add the border width here, because offset* uses padding-edge for the calculations
            initialOffsetX.current = e.offsetX + BORDER_WIDTH
            initialOffsetY.current = e.offsetY + BORDER_WIDTH
            windowRef.current?.classList.add("dragging")

            if (dragTimeout.current !== null) {
                clearTimeout(dragTimeout.current);
                dragTimeout.current = null;
            } else {
                props.desktop.current?.addEventListener("mousemove", updatePosition)
                props.desktop.current?.addEventListener("mouseleave", stopDrag)
            }
        }
    }, []);

    const stopDrag = useCallback((e: MouseEvent) => {
        if (e.button === 0) {
            dragTimeout.current = setTimeout(() => {
                dragTimeout.current = null;
                windowRef.current?.classList.remove("dragging")
                props.desktop.current?.removeEventListener("mousemove", updatePosition)
                props.desktop.current?.removeEventListener("mouseleave", stopDrag)
            }, 50) // intrdouce a small delay where the user can still drag the window without actually pressing down lmb to prevent accidental drops
        }
    }, []);

    return <div class="window" ref={windowRef} style={{ width: props.width, height: props.height, left: x, top: y}}>
        <div class="titlebar" onPointerDown={startDrag} onPointerUp={stopDrag}>
            <div class="title">{props.title}</div>
            <div class="buttons" onPointerDown={e => e.stopPropagation()}>
                <button>
                    <img src="/assets/minimize.png" />
                </button>
                <button>
                    <img src="/assets/maximize.png" />
                </button>
                <button>
                    <img src="/assets/close.png" />
                </button>
            </div>
        </div>
        <div class="content">
            {props.children}
        </div>
    </div>
}

namespace Window {
    export type Props = {
        title: string;
        width?: string | number;
        height?: string | number;
        x?: string | number;
        y?: string | number;
        desktop: RefObject<HTMLDivElement>;
        children: ComponentChildren
    }
}
