import { EEnemySize } from '../../data/EEnemySize';
import { Hex } from '../../util/Hex';
import { PathFinding } from '../../util/PathFinding';
import { SimCommandStartNextWave } from '../commands/SimCommandStartNextWave';
import { SimEnemy } from '../SimEnemy';
import { SimMain } from '../SimMain';
import { ISimAction } from './ISimAction';

export class SimActionSpawnEnemies implements ISimAction {
	public execute(simMain: SimMain) {
		const level = simMain.currentLevel;
		if (!level) {
			return;
		}

		const gdLevel = simMain.gdRoot.levels[level.index];
		const step = level.currentStep;
		const gdWave = gdLevel.waves[level.currentWave];
		if (!gdWave) {
			return;
		}
		
		let spawnDelay = simMain.gdRoot.simulation.spawnDelay;
		switch (gdWave.size) {
			case EEnemySize.Huge:
				spawnDelay *= 2;
				break;
			case EEnemySize.Tiny:
				spawnDelay *= 0.5;
				break;
		}

		if (level.enemiesLeftToSpawn > 0 && level.lastEnemySpawnStep + spawnDelay * simMain.gdRoot.simulation.stepsPerSecond <= level.currentStep) {
			level.enemiesLeftToSpawn -= 1;
			level.lastEnemySpawnStep = step;

			const route = Math.floor(Math.random() * gdLevel.enemyRoutes.length);
			const simEnemy = new SimEnemy(gdWave.enemy, route);
			simEnemy.startHex = gdLevel.enemySpawns[gdLevel.enemyRoutes[route][0]];
			simEnemy.endHex = gdLevel.enemyTargets[gdLevel.enemyRoutes[route][1]];
			simEnemy.position = Hex.toWorld(simEnemy.startHex);
			simEnemy.currentPathPosition = simEnemy.position.clone();
			simEnemy.prevPosition = simEnemy.position.clone();
			const startIndex = level.getCellIndex(simEnemy.startHex);
			const endIndex = level.getCellIndex(simEnemy.endHex);
			const path = PathFinding.bfs(level, startIndex, endIndex);
			simEnemy.path = path!;
			simEnemy.currentPathIndex = 0;
			simEnemy.speed = simMain.gdRoot.enemies[gdWave.enemy].speed;
			simEnemy.currentPathStep = step;
			simEnemy.hitPonts = 10; // TODO gd
			simEnemy.size = EEnemySize.Tiny; // TODO gd
			simEnemy.gain = 10; // TODO gd

			simEnemy.onPathUpdated(level);
			level.enemies.push(simEnemy);
		}

		if (level.nextWaveStep == step && !!gdLevel.waves[level.currentWave + 1]) {
			simMain.addCommand(new SimCommandStartNextWave());
		}
	}
}
