import { IRefPhaserGame, PhaserGame } from './game/PhaserGame';
import "./styles.css";
import styles from './App.module.css';
import { useEffect, useRef, useState } from 'react';
import { ReactComponent as PlayIcon } from './assets/playbutton.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 { getHighScore } from './utils/high-score-store';

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

import { ReactComponent as OnTiltLeftIcon } from "./assets/blocks/ontiltleft.svg";
import { ReactComponent as OnTiltRightIcon } from "./assets/blocks/ontiltright.svg";
import { ReactComponent as OnTiltForwardIcon } from "./assets/blocks/ontiltforward.svg";
import { ReactComponent as OnTiltBackwardIcon } from "./assets/blocks/ontiltbackward.svg";

import { PosterItem } from './types';
import { EventBus } from './game/EventBus';
import Level from './game/scenes/Level';

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: "right", execute: async () => true },
    { icon: BackwardIcon, block: "left", execute: async () => true },
    { icon: UpIcon, block: "up", execute: async () => true },
    { icon: DownIcon, block: "down", execute: async () => true },
]);

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

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

const staticBlockItemsForward: PosterItem[] = repeat(12, [
    { icon: OnTiltForwardIcon, block: "ontiltup", execute: async () => true },
]);

const staticBlockItemsBackward: PosterItem[] = repeat(12, [
    { icon: OnTiltBackwardIcon, block: "ontiltdown", execute: async () => true },
]);

function Maze() {
    const [gameContainerDimensions, setGameContainerDimensions] = useState({ width: "80vw", height: "60vh" });
    const [highScore, setHighScore] = useState(0);
    const [score, setScore] = useState(0);
    const phaserGameRef = useRef<IRefPhaserGame>(null);
    const [connectedCog, setConnectedCog] = useState<RAFT | null>(null);
    const subHelper = useRef<ReturnType<typeof raftDisconnectedSubscriptionHelper> | null>(null);
    const [shouldShowGameFinished, setShouldShowGameFinished] = useState(false);

    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();
        }
    }, []);

    useEffect(() => {
        /* Sets the score when the player goes through the exit or when star is collected */

        const scoreIncreaseHandler = (scene: Level) => {
            setScore(scene.score);
            setHighScore(getHighScore());
        }

        EventBus.on('player-went-through-exit', scoreIncreaseHandler);
        EventBus.on('player-collected-star', scoreIncreaseHandler);

        EventBus.on('game-finished', onGameFinishedHandler);
        return () => {
            EventBus.off('player-went-through-exit');
            EventBus.off('player-collected-star');
            EventBus.off('game-finished', onGameFinishedHandler);
        }
    }, []);

    const onGameFinishedHandler = (scene: Level) => {
        console.log("Game finished");
        setShouldShowGameFinished(oldValue => !oldValue);
    };

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

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

    useEffect(() => {
        setHighScore(getHighScore());
    }, []);


    return (
        <div className={styles.App}>
            {shouldShowGameFinished && <div className={styles.gameFinishedContainer}>
                <p className={styles.gameFinishedText}>🏁 Game Finished 🏁</p> 
            </div>
            }
            <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.blockSelectorContainerTop}>
                    <BlockSelector gameRef={phaserGameRef} staticBlockItems={staticBlockItemsLeft} posterItems={posterItems} staticBlock='left' />
                    <BlockSelector gameRef={phaserGameRef} staticBlockItems={staticBlockItemsRight} posterItems={posterItems} staticBlock='right' />
                </div>
                <div className={styles.blockSelectorContainerBottom}>
                    <BlockSelector gameRef={phaserGameRef} staticBlockItems={staticBlockItemsForward} posterItems={posterItems} staticBlock='up' />
                    <BlockSelector gameRef={phaserGameRef} staticBlockItems={staticBlockItemsBackward} posterItems={posterItems} staticBlock='down' />
                </div>
                <div className={styles.scoreBoard}>
                    <div className={styles.score}>{zeroPrepender(score, 4)}</div>
                </div>
                <PhaserGame ref={phaserGameRef} />
            </div>
            <div className={styles.playBtnContainer}>
                {/* {
                    phaserGameRef.current?.scene?.isGameRunning ? <div />
                        : <PlayIcon
                            className={styles.playBtn}
                            onClick={phaserGameRef.current?.scene?.handleGameStart.bind(phaserGameRef.current?.scene)}
                        />
                } */}
            </div>
        </div>
    )
}

export default Maze;


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