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 { Sky } from './game/entities/Sky';
import { ReactComponent as PlayIcon } from './assets/playbutton.svg';
import { ReactComponent as StarTarget } from './assets/star-target.svg';
import Connection from './connection';
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 BlockSelector from './block-selector';
import OverlayingTutorial from './overlaying-tutorial';
import WonOverlay from './WonOverlay';
import { ReactComponent as StarIcon } from './assets/star.svg';

function JumpingGame() {
    const [gameContainerDimensions, setGameContainerDimensions] = useState({ width: "80vw", height: "60vh" });
    const [collectedStars, setCollectedStars] = useState(0);
    const [isZooming, setIsZooming] = useState(false);
    const phaserGameRef = useRef<IRefPhaserGame>(null);
    const [connectedCog, setConnectedCog] = useState<RAFT | null>(null);
    const [isWinningFlagVisible, setIsWinningFlagVisible] = 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('sky-ready', (sky: Sky) => {
            const skyHeightScaled = sky.height * sky.scaleFactors.height;
            const skyWidthScaled = sky.width * sky.scaleFactors.width;
            setGameContainerDimensions({
                width: skyWidthScaled + "px",
                height: skyHeightScaled + "px"
            });
        });

        EventBus.on('star-collected', (scene_instance: PlayScene) => {
            setCollectedStars(scene_instance.collectedStars);
        });

        EventBus.on('target-achieved', () => {
            if (!phaserGameRef.current) return;
            if (!phaserGameRef.current.scene) return;
            setIsWinningFlagVisible(true);
            setTimeout(() => {
                setIsWinningFlagVisible(false);
            }, 2000);
        });

        EventBus.on('die', () => {
            setCollectedStars(0);
        });

        return () => {
            EventBus.removeListener('sky-ready');
            EventBus.removeListener('play-scene-updated');
            EventBus.removeListener('die');
            EventBus.removeListener('star-collected');}
    }, []);

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

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

    return (
        <div className={styles.App}>
            {isWinningFlagVisible && <WonOverlay />}
            <OverlayingTutorial />
            {/* <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}>
                    <BlockSelector gameRef={phaserGameRef} />
                </div>
                <div className={styles.scoreBoard}>
                    <StarIcon className={styles.starIcon} />
                    <div className={`${styles.score} ${isZooming ? styles.zoom : ''}`}>{collectedStars}</div>
                </div>
                <div className={styles.starTargetContainer}>
                    <StarTarget className={styles.starTargetIcon} />
                </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 JumpingGame;


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);
}