import { SplashComponent } from '../../splash/splash.component';
import { GdRoot } from '../data/GdRoot';
import { ISimAction } from './actions/ISimAction';
import { SimActionFireTowers } from './actions/SimActionFireTowers';
import { SimActionMoveEnemies } from './actions/SimActionMoveEnemies';
import { SimActionMoveProjectiles } from './actions/SimActionMoveProjectiles';
import { SimActionSpawnEnemies } from './actions/SimActionSpawnEnemies';
import { SimCommand } from './commands/SimCommand';
import { SimLevel } from './SimLevel';

export class SimMain {
	currentStep = -1;
	currentLevel: SimLevel | null = null;
	commandHistory: SimCommand[] = [];
	gdRoot: GdRoot = null!;
	interval: number = 0;
	private actions: ISimAction[] = [];

	constructor() {
		this.actions.push(new SimActionMoveEnemies());
		this.actions.push(new SimActionSpawnEnemies());
		this.actions.push(new SimActionFireTowers());
		this.actions.push(new SimActionMoveProjectiles());
	}

	setGdRoot(gdRoot: GdRoot) {
		this.gdRoot = gdRoot;
		this.interval = 1.0 / this.gdRoot.simulation.stepsPerSecond;
		this.currentLevel = new SimLevel(this.gdRoot, 0);
	}

	executeToEnd() {
		this.executeUntilStep(
			this.commandHistory[this.commandHistory.length - 1].step
		);
	}

	executeUntilStep(target: number) {
		this.currentStep = 0;
		while (this.currentStep < target) {
			this.step();
		}
	}

	step() {
		const nextStep = this.currentStep + 1;

		// Get all commands for this step
		const commands = this.commandHistory.filter((c) => c.step === nextStep);

		this.currentStep = nextStep;
		for (const action of this.actions) {
			action.execute(this);
		}

		for (const cmd of commands) {
			cmd.execute(this);
		}
	}

	addCommand(command: SimCommand) {
		this.commandHistory = this.commandHistory.filter(
			(c) => c.step < command.step
		);
		this.commandHistory.push(command);
	}
}
