import { useState, useRef, useEffect } from "react";
import styles from "./style.module.css";
import { PosterItem } from "../types";
import { IRefPhaserGame } from "../game/PhaserGame";
import { IRefPhaserGame as IRefPhaserGameTutorial } from "../tutorial-game/PhaserGame";
import { MdKeyboardArrowUp, MdKeyboardArrowDown } from "react-icons/md";
import { MAIN_BLUE } from "../styles/colors";

interface BlockSelector3Props {
    gameRef: React.RefObject<IRefPhaserGame | IRefPhaserGameTutorial>;
    staticBlock: "left" | "right";
    posterItems: PosterItem[];
    staticBlockItem: PosterItem;
}


export default function BlockSelector3({
    gameRef,
    staticBlock,
    staticBlockItem,
    posterItems,
}: BlockSelector3Props) {
    const containerRef = useRef<HTMLDivElement>(null);
    const scrollContainerRef = useRef<HTMLDivElement>(null);
    const [extendedItems, setExtendedItems] = useState<PosterItem[]>([...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems, ...posterItems]);
    const itemHeight = 50; // We might want to compute this dynamically.
    const staticBlockRef = useRef<HTMLDivElement>(null);
    let scrollTimeout: NodeJS.Timeout | null = null;

    // On mount, set the initial scroll to the middle copy.
    useEffect(() => {
        if (scrollContainerRef.current) {
            scrollContainerRef.current.scrollTop = posterItems.length * itemHeight;
        }
    }, [posterItems, itemHeight]);

    const onBlockChange = (item: PosterItem) => {
        if (!gameRef.current || !gameRef.current.scene) return;
        switch (staticBlock) {
            case "left":
                gameRef.current.scene.selectedCogTiltLeftBlock = item;
                break;
            case "right":
                gameRef.current.scene.selectedCogTiltRightBlock = item;
                break;
        };
    }

    // Use the DOM to determine which poster item is centered under the static block.
    const getSnappedItem = () => {
        if (!staticBlockRef.current || !scrollContainerRef.current) return null;
        // Get the static block's bounding rectangle.
        const staticRect = staticBlockRef.current.getBoundingClientRect();
        const staticCenterY = staticRect.top + staticRect.height / 2;

        // Query all poster items.
        const items = scrollContainerRef.current.querySelectorAll(`.${styles.carouselItem}`);
        let closestItem: Element | null = null;
        let minDistance = Infinity;
        items.forEach((el) => {
            const rect = el.getBoundingClientRect();
            const itemCenterY = rect.top + rect.height / 2;
            const distance = Math.abs(staticCenterY - itemCenterY);
            if (distance < minDistance) {
                minDistance = distance;
                closestItem = el;
            }
        });
        if (closestItem) {
            // Get the index from the data attribute.
            const indexStr = (closestItem as Element).getAttribute("data-index");
            if (indexStr !== null) {
                const extendedIndex = parseInt(indexStr, 10);
                return extendedItems[extendedIndex];
            }
        }
        return null;
    };

    // Handle scroll event to simulate infinite scrolling.
    const handleScroll = () => {
        // append or prepend items in the extendedItems array based on scroll position
        const scrollEl = scrollContainerRef.current;
        if (!scrollEl) return;
        const scrollTop = scrollEl.scrollTop;
        const scrollHeight = scrollEl.scrollHeight;
        const clientHeight = scrollEl.clientHeight;
        const scrollBottom = scrollTop + clientHeight;
        const scrollThreshold = itemHeight * 2;
        if (scrollTop < scrollThreshold) {
            const newItems = extendedItems.slice(-posterItems.length);
            setExtendedItems((prev) => [...newItems, ...prev]);
            scrollEl.scrollTop += itemHeight * posterItems.length;
        }
        else if (scrollBottom > scrollHeight - scrollThreshold) {
            const newItems = extendedItems.slice(0, posterItems.length);
            setExtendedItems((prev) => [...prev, ...newItems]);
            scrollEl.scrollTop -= itemHeight * posterItems.length;
        }
        // Determine the snapped item.
        if (scrollTimeout) {
            clearTimeout(scrollTimeout);
        }
        scrollTimeout = setTimeout(() => {
            const snappedItem = getSnappedItem();
            if (snappedItem) {
                onBlockChange(snappedItem);
            }
        }, 200);
    };

    const scrollByItem = (direction: "up" | "down") => {
        const scrollEl = scrollContainerRef.current;
        if (!scrollEl) return;
        const delta = direction === "up" ? -itemHeight : itemHeight;
        scrollEl.scrollBy({ top: delta, behavior: "smooth" });
    };

    const handleArrowUpClick = () => {
        scrollByItem("up");
    };

    const handleArrowDownClick = () => {
        scrollByItem("down");
    };

    return (
        <div className={styles.outerContainer}>
            <div className={styles.upArrowContainer} onClick={handleArrowUpClick}>
                <MdKeyboardArrowUp color={MAIN_BLUE} size={40} />
            </div>
            <div ref={containerRef} className={styles.carouselBody}>
                {/* The static block stays fixed */}
                <div ref={staticBlockRef} className={styles.staticBlockItem}>
                    <staticBlockItem.icon className={styles.staticBlockItemIcon} />
                </div>
                {/* The scrollable list */}
                <div
                    ref={scrollContainerRef}
                    className={styles.scrollContainer}
                    onScroll={handleScroll}
                >
                    {extendedItems.map((item, index) => (
                        <div
                            key={index + item.block}
                            data-index={index}  // Tag each item with its index.
                            className={styles.carouselItem}>
                            <item.icon className={styles.carouselItemIcon} />
                        </div>
                    ))}
                </div>
            </div>
            <div className={styles.downArrowContainer} onClick={handleArrowDownClick}>
                <MdKeyboardArrowDown color={MAIN_BLUE} size={40} />
            </div>
        </div>
    );
}