import Phaser from 'phaser';
import { signal, useSignal, useSignalEffect } from '@preact/signals';
import { createContext, h } from 'preact';
import { useContext } from 'preact/hooks';
import {ReadonlySignal} from "@preact/signals-core";
import type { ReactiveScene, ReactiveScenePhaserData } from '../scenes';

export interface PhaserGameContext {
    game: Phaser.Game;
}

export const phaserContext = createContext<ReadonlySignal<PhaserGameContext> | null>(null);

export const defaultPhaserConfig: Phaser.Types.Core.GameConfig = {
    type: Phaser.AUTO,
    width: 560,
    height: 560,
    parent: 'phaser-container',
    backgroundColor: '#f9fafb',
    scene: [],
};

export interface PhaserGameProps {
    config?: Partial<Phaser.Types.Core.GameConfig>;
    children?: any;
}

export function PhaserGame(props: PhaserGameProps) {
    const gameSignal = useSignal<PhaserGameContext>({ game: undefined! });

    useSignalEffect(() => {
        const config: Phaser.Types.Core.GameConfig = {
            ...defaultPhaserConfig,
            ...props.config,
        };
        const phaserGame = new Phaser.Game(config);
        gameSignal.value = { game: phaserGame };

        return () => {
            gameSignal.value = { game: undefined! };
            phaserGame.destroy(true);
        };
    });

    return (
        <div id="phaser-container" className="w-full h-full">
            <phaserContext.Provider value={gameSignal}>
                {props.children}
            </phaserContext.Provider>
        </div>
    );
}

export interface PhaserSceneProps<TData extends Record<string, unknown> = {}> {
    sceneKey: string;
    scene: ReactiveScene<TData>;
    autoStart: boolean;
    data?: TData;
    children?: any;
}

export const phaserSceneContext = createContext<ReadonlySignal<ReactiveScene> | null>(null);
export function PhaserScene<TData extends Record<string, unknown> = {}>(props: PhaserSceneProps<TData>) {
    const phaserGameSignal = useContext(phaserContext);
    const sceneSignal = useSignal<Phaser.Scene>();

    useSignalEffect(() => {
        if (!phaserGameSignal) return;
        const ctx = phaserGameSignal.value;
        if (!ctx?.game) return;

        const game = ctx.game;
        const initData = {
            ...props.data,
            phaserGame: phaserGameSignal.value,
        } as TData & ReactiveScenePhaserData;

        game.scene.add(props.sceneKey, props.scene, props.autoStart, initData);
        sceneSignal.value = game.scene.getScene(props.sceneKey);
        return () => {
            sceneSignal.value = undefined;
            game.scene.remove(props.sceneKey);
        };
    });

    return <phaserSceneContext.Provider value={sceneSignal as ReadonlySignal<ReactiveScene>}>{props.children}</phaserSceneContext.Provider>;
}
