import { GdRoot } from "../GameData/index.js";
import { ISimAction, ISimCommand, SimActionFireTowers, SimActionMoveEnemies, SimActionMoveProjectiles, SimActionSpawnEnemies, SimCommandStartNextWave, SimLevel } from "./index.js";

export class SimMain {
    private _currentLevel: SimLevel;
    private _commands: ISimCommand[] = [];
    private _actions: ISimAction[] = [];
    private _gdRoot: GdRoot;

    constructor(gdRoot: GdRoot, level: number) {
        this._gdRoot = gdRoot;
        this._currentLevel = new SimLevel(gdRoot, level);
        this._actions.push(new SimActionMoveEnemies());
        this._actions.push(new SimActionSpawnEnemies());
        this._actions.push(new SimActionFireTowers());
        this._actions.push(new SimActionMoveProjectiles());
        if (true || !this.loadModel()) {
            this.reload();
        }

        this._currentLevel.paused = true;
    }

    public get gdRoot(): GdRoot {
        return this._gdRoot;
    }

    public get currentLevel(): SimLevel {
        return this._currentLevel;
    }

    public executeUntilStep(targetStep: number) {
        this.executeCommands();
        while (this._currentLevel.currentStep < targetStep) {
            this.executeOneStep();
            this._currentLevel.currentStep += 1;
        }
    }

    private executeCommands() {
        const saveModel = false && this._commands.length != 0;
        this._commands.forEach((command) => {
            command.execute();
        });
        this._commands = [];
        if (saveModel) {
            this.saveModel();
        }
    }

    private executeOneStep() {
        for (const action of this._actions)
            action.execute(this);
    }

    public addCommand(command: ISimCommand) {
        this._commands[this._commands.length] = command;
    }

    public reload() {
        this._currentLevel = new SimLevel(this._gdRoot, 0);
        this.saveModel();
        this.addCommand(new SimCommandStartNextWave(this._gdRoot, this._currentLevel));
    }

    private loadModel(): boolean {
        if (!!localStorage.htd) {
            const savedLevel = SimLevel.deserialize(this._gdRoot, localStorage.htd);
            if (!savedLevel)
                return false;

            this._currentLevel = savedLevel;
            return true;
        }

        return false;
    }

    private saveModel() {
        localStorage.htd = this._currentLevel.serialize();
    }
}
