import { IRefPhaserGame, PhaserGame } from './game/PhaserGame';
import "./styles.css";
import styles from './App.module.css';
import { useEffect, useRef, useState } from 'react';
import { EventBus } from './game/EventBus';
import PlayScene from './game/scenes/PlayScene';
import { Mountain } from './game/entities/Mountain';
import { ReactComponent as FlagsTarget } from './assets/flags-target-small.svg';
import { raftDisconnectedSubscriptionHelper } from './utils/raft-subscription-helpers';
import RAFT from '@robotical/webapp-types/dist-types/src/application/RAFTs/RAFT';
import { RaftTypeE } from '@robotical/webapp-types/dist-types/src/types/raft';
import OverlayingTutorial from './overlaying-tutorial';
import WonOverlay from './WonOverlay';
import { ReactComponent as StarIcon } from './assets/flags.svg';
import { PosterItem } from './types';

import { ReactComponent as OnTiltLeft } from "./assets/blocks/ontiltleft.svg";
import { ReactComponent as OnTiltRight } from "./assets/blocks/ontiltright.svg";

import { ReactComponent as ForwardIcon } from "./assets/blocks/forward.svg";
import { ReactComponent as BackwardIcon } from "./assets/blocks/backward.svg";

import { ReactComponent as NowhereIcon } from "./assets/blocks/nowhere.svg";

import BlockSelector2 from "./block-selector";
import { selectedBlockFromTutorialForLeft, selectedBlockFromTutorialForRight } from './utils/selected-blocks-from-tutorial';
import ShouldIStayOrShouldIGo from './ShouldIStayOrShouldIGo';


// const posterItemsLeft: PosterItem[] = [
//     { icon: ForwardIcon, block: "moveright", execute: async () => true },
// ];
// const posterItemsRight: PosterItem[] = [
//     { icon: BackwardIcon, block: "moveleft", execute: async () => true },
// ];

const staticBlockItemUp: PosterItem = { icon: OnTiltLeft, block: "ontiltleft", execute: async () => true };

const staticBlockItemDown: PosterItem = { icon: OnTiltRight, block: "ontiltright", execute: async () => true };

const repeat = (n: number, array: PosterItem[]) => {
    /* Repeats every element in the array until the array length = n */
    return Array(n).fill(array).flat().slice(0, n);
}

const posterItems: PosterItem[] = repeat(12, [
    { icon: ForwardIcon, block: "moveright", execute: async () => true },
    { icon: NowhereIcon, block: "dontmove", execute: async () => true },
    { icon: BackwardIcon, block: "moveleft", execute: async () => true },
]);

// const staticBlockItemsUp: PosterItem[] = repeat(12, [
//     { icon: OnTiltLeft, block: "ontiltleft", execute: async () => true },
// ]);

// const staticBlockItemsDown: PosterItem[] = repeat(12, [
//     { icon: OnTiltRight, block: "ontiltright", execute: async () => true },
// ]);

function Skiing() {
    const [gameContainerDimensions, setGameContainerDimensions] = useState({ width: "70vw", height: "80vh" });
    const [collectedFlags, setCollectedFlags] = useState(0);
    const [collectedFlagsText, setCollectedFlagsText] = useState("");
    const [isZooming, setIsZooming] = useState(false);
    const [isZoomingCenteredScore, setIsZoomingCenteredScore] = useState(false);
    const phaserGameRef = useRef<IRefPhaserGame>(null);
    const [connectedCog, setConnectedCog] = useState<RAFT | null>(null);
    const [isWinningFlagVisible, setIsWinningFlagVisible] = useState(false);
    const [isSceneReady, setIsSceneReady] = useState(false);
    const [posterItemsLeftState, setPosterItemsLeftState] = useState<PosterItem[]>([]);
    const [posterItemsRightState, setPosterItemsRightState] = useState<PosterItem[]>([]);
    const [tutorialPhase, setTutorialPhase] = useState<undefined | number>(1);
    const [shouldIStayOrShouldIGoVisible, setShouldIStayOrShouldIGoVisible] = useState(false);

    const subHelper = useRef<ReturnType<typeof raftDisconnectedSubscriptionHelper> | null>(null);

    useEffect(() => {
        /* Checks if we are already connected to a cog */
        const selectedCog = window.applicationManager?.getTheCurrentlySelectedDeviceOrFirstOfItsKind(RaftTypeE.COG);
        if (selectedCog) {
            setConnectedCog(selectedCog);
            subHelper.current = raftDisconnectedSubscriptionHelper(selectedCog);
            subHelper.current.subscribe(() => {
                setConnectedCog(null);
                subHelper.current?.unsubscribe();
            });
        }

        return () => {
            subHelper.current?.unsubscribe();
        }
    }, []);

    const handleConnect = () => {
        window.applicationManager?.connectGenericCog((raft) => {
            setConnectedCog(raft);
            subHelper.current = raftDisconnectedSubscriptionHelper(raft);
            subHelper.current.subscribe(() => {
                setConnectedCog(null);
                subHelper.current?.unsubscribe();
            });
        });
    };

    const handleDisconnect = () => {
        if (connectedCog) {
            window.applicationManager?.disconnectGeneric(connectedCog);
        }
    };

    useEffect(() => {
        EventBus.on('mountain-ready', (mountain: Mountain) => {
            const mountainHeightScaled = mountain.height * mountain.scaleFactors.height;
            const mountainWidthScaled = mountain.width * mountain.scaleFactors.width;
            setGameContainerDimensions({
                width: mountainWidthScaled + "px",
                height: mountainHeightScaled + "px"
            });
            setIsSceneReady(true);
        });

        EventBus.on('flags-collected', (scene_instance: PlayScene) => {
            setCollectedFlags(scene_instance.collectedFlags);
            setCollectedFlagsText(`+1=${scene_instance.collectedFlags}`);
        });

        EventBus.on('flags-lost', (scene_instance: PlayScene) => {
            setCollectedFlags(scene_instance.collectedFlags);
            setCollectedFlagsText(`-1=${scene_instance.collectedFlags}`);
        });

        EventBus.on('target-achieved', () => {
            if (!phaserGameRef.current) return;
            if (!phaserGameRef.current.scene) return;
            setIsWinningFlagVisible(true);
            setTimeout(() => {
                setIsWinningFlagVisible(false);
                setShouldIStayOrShouldIGoVisible(true);
                // window.applicationManager.carouselNavigatorManager.getNavigator("games")?.setIsVisible(true);
                // window.applicationManager.carouselNavigatorManager.getNavigator("games")?.setHighlightedItem("/maze");
            }, 2000);
        });

        EventBus.on('die', () => {
            setCollectedFlags(0);
            setTutorialPhase(3);
            setPosterItemsLeftState([]);
            setPosterItemsRightState([]);
        });

        return () => {
            EventBus.removeListener('mountain-ready');
            EventBus.removeListener('die');
            EventBus.removeListener('flags-collected');
            EventBus.removeListener('flags-lost');
            EventBus.removeListener('target-achieved');
        }
    }, []);

    useEffect(() => {
        if (collectedFlags > 0) {
            setIsZooming(true);
            setTimeout(() => {
                setIsZooming(false);
            }, 300);
        }
    }, [collectedFlags]);

    useEffect(() => {
        if (collectedFlags > 0) {
            setIsZoomingCenteredScore(true);
            setTimeout(() => {
                setIsZoomingCenteredScore(false);
            }, 1500);
        }
    }, [collectedFlags]);

    const onPlayBtnClick = () => {
        // if cog is connected, start the game, otherwise connect a cog
        if (connectedCog) {
            phaserGameRef.current?.scene?.handleGameStart();
        } else {
            handleConnect();
        }
    };

    const onTutorialFinished = () => {
        // when the tutorial is finished, we get the selected blocks from the programming phase
        // and we push them to the poster items

        // const selectedBlockLeft = selectedBlockFromTutorialForLeft;
        // const selectedBlockRight = selectedBlockFromTutorialForRight;
        // if (selectedBlockLeft) {
        //     setPosterItemsLeftState([selectedBlockLeft]);
        // }
        // if (selectedBlockRight) {
        //     setPosterItemsRightState([selectedBlockRight]);
        // }

        const selectedBlockLeft = selectedBlockFromTutorialForLeft;
        const selectedBlockRight = selectedBlockFromTutorialForRight;
        if (selectedBlockLeft) {
            const index = posterItems.findIndex(item => item.block === selectedBlockLeft.block);
            if (index !== -1) {
                const selectedBlock = posterItems[index];
                posterItems.splice(index, 1);
                posterItems.unshift(selectedBlock);
                setPosterItemsLeftState([...posterItems]);
            }
        }
        if (selectedBlockRight) {
            const index = posterItems.findIndex(item => item.block === selectedBlockRight.block);
            if (index !== -1) {
                const selectedBlock = posterItems[index];
                posterItems.splice(index, 1);
                posterItems.unshift(selectedBlock);
                setPosterItemsRightState([...posterItems]);
            }
        }
        setTutorialPhase(undefined);
    };

    const onKeepPlaying = () => {
        setShouldIStayOrShouldIGoVisible(false);
        setCollectedFlags(0);
        setCollectedFlagsText("");
        setTutorialPhase(3);
        setPosterItemsLeftState([]);
        setPosterItemsRightState([]);
    };

    const onGoNext = () => {
        window.applicationManager.carouselNavigatorManager.getNavigator("games")?.navigate("/cog-shooter-game");
    };

    return (
        <div className={styles.App}>
            {isWinningFlagVisible && <WonOverlay />}
            {shouldIStayOrShouldIGoVisible && <ShouldIStayOrShouldIGo keepPlaying={onKeepPlaying} goNext={onGoNext} />}
            <OverlayingTutorial tutorialPhase={tutorialPhase} setTutorialPhase={setTutorialPhase} onTutorialFinished={onTutorialFinished} />
            {/* <div className={styles.highScoreBoard}>
                <h1>HIGH SCORE</h1>
                <div className={styles.highScore}>{zeroPrepender(highScore, 4)}</div>
            </div> */}
            <div className={styles.gameContainer} style={gameContainerDimensions}>
                {/* <div className={styles.connectionButtonsContainer}>
                    <Connection
                        connectedCog={connectedCog}
                        setConnectedCog={setConnectedCog}
                        handleDisconnect={handleDisconnect}
                        handleConnect={handleConnect}
                    />
                </div> */}
                <div className={styles.blockSelectorContainer}>
                    {isSceneReady && (
                        <>
                            {/* {!!posterItemsRightState.length && <BlockSelector2 gameRef={phaserGameRef} staticBlock="right" posterItems={posterItemsRightState} staticBlockItem={staticBlockItemDown} snapPointFactors={[.48,]} />} */}
                            {/* {!!posterItemsLeftState.length && <BlockSelector2 gameRef={phaserGameRef} staticBlock="left" posterItems={posterItemsLeftState} staticBlockItem={staticBlockItemUp} snapPointFactors={[.48,]} />} */}
                            {!!posterItemsRightState.length && <BlockSelector2 gameRef={phaserGameRef} staticBlock="right" posterItems={posterItemsRightState} staticBlockItems={[staticBlockItemDown]} />}
                            {!!posterItemsLeftState.length && <BlockSelector2 gameRef={phaserGameRef} staticBlock="left" staticBlockItems={[staticBlockItemUp]} posterItems={posterItemsLeftState} />}
                        </>
                    )}
                </div>
                <div className={styles.scoreBoard}>
                    <StarIcon className={styles.starIcon} />
                    <div className={`${styles.score} ${isZooming ? styles.zoom : ''}`}>{collectedFlags}</div>
                </div>
                <div className={`${styles.centeredScore} ${isZoomingCenteredScore ? styles.flashScore : ''}`}>
                    {collectedFlagsText}
                </div>
                <div className={styles.flagsTargetContainer}>
                    <FlagsTarget className={styles.flagsTargetIcon} />
                </div>
                <PhaserGame ref={phaserGameRef} />
            </div>
            {/* <div className={styles.playBtnContainer}>
                {
                    (!phaserGameRef.current?.scene?.isGameRunning && !phaserGameRef.current?.scene?.isGameOverVisible) ? <PlayIcon
                        className={styles.playBtn}
                        onClick={onPlayBtnClick}
                    />
                        : <div />
                }
            </div> */}
        </div>
    )
}

export default Skiing;


function zeroPrepender(num: number, size: number): string {
    // helper function that prepends zeros to a number if it is less than a certain size
    // and also keeps only the first 'size' digits of the number if it is greater than 'size'
    let s = num + "";
    while (s.length < size) s = "0" + s;
    return s.slice(0, size);
}