import { useCallback, useEffect, useRef, useState } from "react";
import { ReactComponent as TickIcon } from "../assets/green-tick.svg";
import styles from "./styles.module.css";
import { IRefPhaserGame, PhaserGame } from "../tutorial-game/PhaserGame";
import { PosterItem } from "../types";
import PlayScene from "../tutorial-game/scenes/PlayScene";

import { ReactComponent as OnTouchCogIcon } from "../assets/blocks/ontouchcog.svg";
import { ReactComponent as OnNoTouchCogIcon } from "../assets/blocks/onnotouchcog.svg";

import { ReactComponent as UpIcon } from "../assets/blocks/up.svg";
import { ReactComponent as DownIcon } from "../assets/blocks/down.svg";
import { ReactComponent as NowhereIcon } from "../assets/blocks/nowhere.svg";
import BlockSelector4 from "../block-selector-4";

import { setSelectedBlockFromTutorialForClick, setSelectedBlockFromTutorialForNoClick } from "../utils/selected-blocks-from-tutorial";
import { getConnectedCog, hasMartyWebAppHost } from "../utils/CogManager";
import { CommandPair, FallbackCogButton, SuccessBadge, TutorialFrame } from "./TutorialFrame";
import type { TutorialSelections } from ".";

const posterItemsNoClick: PosterItem[] = [
    { icon: UpIcon, block: "moveup", execute: async () => true },
    { icon: NowhereIcon, block: "dontmove", execute: async () => true },
    { icon: DownIcon, block: "movedown", execute: async () => true },
];

const posterItemsClick: PosterItem[] = [
    { icon: UpIcon, block: "moveup", execute: async () => true },
    { icon: NowhereIcon, block: "dontmove", execute: async () => true },
    { icon: DownIcon, block: "movedown", execute: async () => true },
];

const staticBlockItemUp: PosterItem = { icon: OnTouchCogIcon, block: "ontouchcog", execute: async () => true };
const staticBlockItemDown: PosterItem = { icon: OnNoTouchCogIcon, block: "onnotouchcog", execute: async () => true };
const defaultClickBlock = posterItemsClick[0];
const defaultNoClickBlock = posterItemsNoClick[2];

type Props = {
    nextPhase: (selectedBlocks: TutorialSelections) => void;
};

export function Phase4({ nextPhase }: Props) {
    const [gameContainerDimensions, setGameContainerDimensions] = useState({
        width: "min(42vw, 620px)",
        height: "min(30vh, 320px)",
        visibility: "hidden",
    } as React.CSSProperties);
    const [blocksIconState, setBlocksIconState] = useState<"visible" | "animation">("visible");
    const [isComplete, setIsComplete] = useState(false);
    const [shouldShowFallbackPress] = useState(() => !hasMartyWebAppHost() && !getConnectedCog());
    const [selectedClickBlock, setSelectedClickBlock] = useState<PosterItem>(defaultClickBlock);
    const [selectedNoClickBlock, setSelectedNoClickBlock] = useState<PosterItem>(defaultNoClickBlock);
    const phaserGameRef = useRef<IRefPhaserGame>(null);
    const selectedClickBlockRef = useRef<PosterItem>(defaultClickBlock);
    const selectedNoClickBlockRef = useRef<PosterItem>(defaultNoClickBlock);
    const completionStarted = useRef(false);
    const nextPhaseTimeoutRef = useRef<number | undefined>();

    const onSelectedClickBlockChange = useCallback((block: PosterItem) => {
        selectedClickBlockRef.current = block;
        setSelectedClickBlock(block);
    }, []);

    const onSelectedNoClickBlockChange = useCallback((block: PosterItem) => {
        selectedNoClickBlockRef.current = block;
        setSelectedNoClickBlock(block);
    }, []);

    const completeStep = useCallback(() => {
        if (completionStarted.current) return;
        completionStarted.current = true;
        const clickBlock = selectedClickBlockRef.current;
        const noClickBlock = selectedNoClickBlockRef.current;

        setSelectedBlockFromTutorialForClick(clickBlock);
        setSelectedBlockFromTutorialForNoClick(noClickBlock);
        setBlocksIconState("animation");
        setIsComplete(true);
        nextPhaseTimeoutRef.current = window.setTimeout(() => nextPhase({
            click: clickBlock,
            noClick: noClickBlock,
        }), 900);
    }, [nextPhase]);

    const setFallbackInputState = useCallback((button: "click" | "release") => {
        const scene = phaserGameRef.current?.scene;
        if (!scene?.player || completionStarted.current) return;
        scene.isGameRunning = true;
        scene.previewInputState = button;
        scene.selectedCogClickedBlock = selectedClickBlockRef.current;
        scene.selectedCogNoClickBlock = selectedNoClickBlockRef.current;
    }, []);

    const startFallbackPress = useCallback((event: React.PointerEvent<HTMLButtonElement>) => {
        event.preventDefault();
        setFallbackInputState("click");
    }, [setFallbackInputState]);

    const stopFallbackPress = useCallback((event?: React.PointerEvent<HTMLButtonElement>) => {
        event?.preventDefault();
        setFallbackInputState("release");
    }, [setFallbackInputState]);

    const handleCurrentSceneReady = useCallback((scene: PlayScene) => {
        scene.isPreviewOnly = true;
        scene.isGameRunning = true;
        scene.previewInputState = "release";
        scene.physics.resume();
        scene.anims.resumeAll();
        scene.selectedCogClickedBlock = selectedClickBlockRef.current;
        scene.selectedCogNoClickBlock = selectedNoClickBlockRef.current;
        scene.obstacles?.clear(true, true);
        scene.stars?.clear(true, true);
        scene.shinyStars?.clear(true, true);
        scene.gameOverContainer?.setAlpha(0);
        scene.isGameOverVisible = false;
        scene.sky?.scaleToFit();
        scene.ground?.scaleToFit();
        scene.ground?.positionOnSky();
        scene.player?.setTexture("marty-in-plane");
        scene.player?.scaleToFit();
        scene.player?.positionOnSky();
        setGameContainerDimensions(currentDimensions => ({
            ...currentDimensions,
            visibility: "visible"
        }));
    }, []);

    useEffect(() => {
        return () => {
            if (nextPhaseTimeoutRef.current) {
                window.clearTimeout(nextPhaseTimeoutRef.current);
            }
        }
    }, []);

    const blocksIconContainerClasses = [
        styles.doubleColumnContainer,
        blocksIconState === "animation" ? styles.fadeOutAnimation : "",
    ].join(" ");

    return (
        <TutorialFrame
            stepIndex={0}
            title="Choose Flight Controls"
            hint="Pick what Robofly does while Cog is pressed, and what it does when Cog is released."
            controls={
                <>
                    <CommandPair CogIcon={OnTouchCogIcon} ActionIcon={selectedClickBlock.icon} />
                    <CommandPair CogIcon={OnNoTouchCogIcon} ActionIcon={selectedNoClickBlock.icon} />
                    {shouldShowFallbackPress ? (
                        <button
                            className={styles.fallbackButton}
                            type="button"
                            onPointerDown={startFallbackPress}
                            onPointerUp={stopFallbackPress}
                            onPointerCancel={stopFallbackPress}
                            onPointerLeave={stopFallbackPress}
                            disabled={isComplete}
                        >
                            Press
                        </button>
                    ) : null}
                    <FallbackCogButton onPress={completeStep} disabled={isComplete} label="Continue" />
                </>
            }
            badge={isComplete ? <SuccessBadge TickIcon={TickIcon} /> : null}
        >
            <div className={blocksIconContainerClasses}>
                <div className={`${styles.doubleBlockSelectorContainer} ${styles.selectorFocusAnchor}`}>
                    <BlockSelector4
                        gameRef={phaserGameRef}
                        staticBlock="up"
                        posterItems={posterItemsClick}
                        staticBlockItem={staticBlockItemUp}
                        onSelectedBlockChange={onSelectedClickBlockChange}
                        initialSelectedIndex={0}
                    />
                    <BlockSelector4
                        gameRef={phaserGameRef}
                        staticBlock="down"
                        posterItems={posterItemsNoClick}
                        staticBlockItem={staticBlockItemDown}
                        onSelectedBlockChange={onSelectedNoClickBlockChange}
                        initialSelectedIndex={2}
                    />
                </div>
                <div className={styles.gameContainer} style={gameContainerDimensions}>
                    <PhaserGame ref={phaserGameRef} currentActiveScene={handleCurrentSceneReady} />
                </div>
            </div>
        </TutorialFrame>
    );
}
