import { GdProjectileEffect } from "../data/GdProjectileEffect";
import { Vector2 } from "../util/Vector2";
import { SimLevel } from "./SimLevel";
import { SimProjectile } from "./SimProjectile";

export class SimTower {
	lastProjectileStep: number = -1;
	lastAoeStep: number = -1;
	projectileEffect: GdProjectileEffect | null = null;
	projectileRange: number = -1;
	projectileRate: number = -1;
	projectileSize: number = -1;
	aoeEffect: number = -1;
	aoeRange: number = -1;
	aoeRate: number = -1;
	position: Vector2 = new Vector2(0, 0);
	currentProjectileTarget: number = -1;
	index: number = -1;

    constructor(index: number, position: Vector2) {
        this.index = index;
        this.position = position;
    }

    public fireIfAble(level: SimLevel) {
        const currentStep = level.currentStep;
        if (this.canFireProjectile(level) && !!this.projectileEffect) {
            level.projectiles.push(new SimProjectile(currentStep, level.projectiles.length, this.position, this.pickProjectileTarget(level), this.projectileSize, this.projectileEffect));
            this.lastProjectileStep = currentStep;
        }
        if (this.canFireAoe(level)) {
            // TODO
        }
    }

    private canFireProjectile(level: SimLevel) {
        if (!this.projectileEffect)
            return false;

        const currentStep = level.currentStep;
        if (this.lastProjectileStep == -1 || this.lastProjectileStep + this.projectileRate < currentStep) {
            return this.isEnemyInRange(level, this.projectileRange);
        }
        return false;
    }

    private canFireAoe(level: SimLevel) {
        const currentStep = level.currentStep;
        if (this.aoeEffect != null) {
            if (this.lastAoeStep == -1 || this.lastAoeStep + this.aoeRate < currentStep) {
                return this.isEnemyInRange(level, this.aoeRange);
            }
        }
        return false;
    }

    private pickProjectileTarget(level: SimLevel) {
        if (this.currentProjectileTarget != -1) {
            return this.currentProjectileTarget;
        }

        let minLength = -1;
        let candidate = -1;
        for (let idx = 0; idx < level.enemies.length; idx++) {
            const enemy = level.enemies[idx];
            const delta = enemy.currentPathPosition.subtract(this.position);
            const length = delta.magnitude();
            if (enemy.path != null && length < this.projectileRange) {
                const pathLength = enemy.path.length - enemy.currentPathIndex;
                if (minLength == -1 || pathLength < minLength) {
                    candidate = idx;
                    minLength = pathLength;
                }
            }
        }

        return candidate;
    }

    private isEnemyInRange(level: SimLevel, range: number) {
        for (const idx in level.enemies) {
            const enemy = level.enemies[idx];
            const delta = enemy.currentPathPosition.subtract(this.position);
            const length = delta.magnitude();
            if (length < range) {
                return true;
            }
        }
        return false;
    }
}
