import { ENEMIES_CONFIG } from './enemiesConfig.js';
import { TOWERS_CONFIG } from './towerConfig.js';

export class TowerManager {

    constructor(scene) {
        this.scene = scene;
        this.lastFired = {}; // Track last fire time for each tower
        this.following = {};

        this.createAnims();
    }

    createTower(type, x, y) {
        const posX = this.scene.gridToLocation(x);
        const posY = this.scene.gridToLocation(y);

        const towerBase = this.scene.add.sprite(posX, posY, 'towers', 7);
        const tower = this.scene.add.sprite(posX, posY, 'towers', TOWERS_CONFIG[type].spriteStart);
        tower.props = {
            'type': type,
            'level': 1
        }

        // Generate unique ID for enemy
        const uniqueId = Phaser.Math.Between(100000, 999999);
        tower.id = uniqueId;

        this.scene.towers.add(tower);

        // Draw range circle
        const config = TOWERS_CONFIG[type].level1;
        if (config) {
            const range = config.range;
            tower.showRange = this.scene.add.circle(posX, posY, range, 0x00ff00, 0);
        }
    }

    update(time, delta) {
        // Iterate through all towers
        this.scene.towers.children.iterate((tower) => {
            const towerX = tower.x;
            const towerY = tower.y;
            
            // Get tower config
            const type = tower.props.type;
            const level = 'level'+tower.props.level;
            const config = TOWERS_CONFIG[type][level];

            if (this.following.hasOwnProperty(tower.id)) {
                this.scene.enemies.children.iterate((enemy) => {
                    if (this.following[tower.id] === enemy.props.id) {
                        // Rotate tower to face the enemy
                        const angle = Phaser.Math.Angle.Between(towerX, towerY, enemy.x, enemy.y);
                        tower.rotation = angle;
                    }
                });
            }
            
            if (!config) return;

            const range = config.range;
            const rate = config.rate;
            
            // Check if enough time has passed since last fire
            if (this.lastFired[tower.id] === undefined || 
                time - this.lastFired[tower.id] >= rate) {
                
                // Check for enemies in range
                let enemiesInRange = [];
                this.scene.enemies.children.iterate((enemy) => {
                    const distanceTraveled = enemy.props.distanceTraveled;
                    const distance = Phaser.Math.Distance.Between(
                        towerX, towerY,
                        enemy.x, enemy.y
                    );
                    
                    if (distance <= range && enemy.props.health > 0) {
                        enemiesInRange.push(enemy);
                    }
                });
                
                // Fire if enemies are in range
                if (enemiesInRange.length > 0) {
                    
                    // Find enemy with greatest distance traveled
                    const furthestEnemy = enemiesInRange.reduce((max, current) => {
                        return current.props.distanceTraveled > max.props.distanceTraveled ? current : max;
                    });
                    
                    this.following[tower.id] = furthestEnemy.props.id;
                    const dmgType = TOWERS_CONFIG[tower.props.type].dmgType;
                    if (dmgType === 'aoe') {
                        this.aoeAttackTarget(tower, furthestEnemy);
                    } else {
                        this.attackTarget(tower, furthestEnemy);
                    }
                    
                    this.lastFired[tower.id] = time;
                }
            }
        });
    }

    attackTarget(tower, enemy) {
        // Tower Properties
        const type = tower.props.type;
        const level = 'level'+tower.props.level;
        const config = TOWERS_CONFIG[type][level];
        const duration = TOWERS_CONFIG[type][level].duration;
        
        if (!config) return;

        const dmgLow = config.dmgLow;
        const dmgHigh = config.dmgHigh;

        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
        tower.rotation = angle;

        tower.play(`${type}-${level}-fire`, { 'duration': duration });

        // Calculate damage (random between low and high)
        const damage = Phaser.Math.Between(dmgLow, dmgHigh);
        
        // Apply damage to enemy
        enemy.props.health -= damage;

        if (enemy.props.health > 0) {
            this.createHealthBar(enemy);
            if (type === 'gun') {
                const gunfire = this.scene.physics.add.sprite(enemy.x, enemy.y, 'ammo', 0);
                gunfire.play('gunfire');
                gunfire.setVelocity(enemy.body.velocity.x, enemy.body.velocity.y);
                this.scene.time.delayedCall(config.duration, () => {
                    gunfire.destroy();
                });
            }
        } else {
            this.destroyEnemy(enemy, tower);
        }
    }

    aoeAttackTarget(tower, enemy) {
        // Tower Properties
        const type = tower.props.type;
        const level = 'level'+tower.props.level;
        const config = TOWERS_CONFIG[type][level];
        const duration = TOWERS_CONFIG[type][level].duration;
        
        if (!config) return;

        const dmgLow = config.dmgLow;
        const dmgHigh = config.dmgHigh;

        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, enemy.x, enemy.y);
        tower.rotation = angle;

        if (type === 'cannon') {
            const projDistance = 50;
            const projX = tower.x + Math.cos(angle) * projDistance;
            const projY = tower.y + Math.sin(angle) * projDistance;
            const projectile = this.scene.add.sprite(projX, projY, 'ammo', 3);
            this.scene.tweens.add({
                targets: projectile,
                x: enemy.x,
                y: enemy.y,
                duration: 100,
                onComplete: () => {
                    projectile.setTexture('ammo', 4);
                    this.scene.time.delayedCall(200, () => {
                        projectile.destroy();
                    });
                }
            });
            tower.play(`${type}-${level}-fire`, { 'duration': duration });
        }

        if (type === 'flame') {
            const projDistance = 185;
            const projDistance2 = 220;
            const projX = tower.x + Math.cos(angle) * projDistance;
            const projY = tower.y + Math.sin(angle) * projDistance;
            const proj2X = tower.x + Math.cos(angle) * projDistance2;
            const proj2Y = tower.y + Math.sin(angle) * projDistance2;
            const projectile = this.scene.add.sprite(projX, projY, 'towers', 23).setScale(1.5).setAlpha(.5);
            projectile.rotation = angle;
            projectile.play(`flamethrower`);
            this.scene.tweens.add({
                targets: projectile,
                x: proj2X,
                y: proj2Y,
                duration:1000,
                onComplete: () => {
                    projectile.destroy();
                }
            });
            
        }

        // Calculate damage (random between low and high)
        const damage = Phaser.Math.Between(dmgLow, dmgHigh);

        // Get AOE distance
        const aoeDistance = config.aoe;

        // Apply damage to all enemies in range
        const enemiesInRange = this.scene.enemies.getChildren().filter(e => {
            return Phaser.Math.Distance.Between(e.x, e.y, enemy.x, enemy.y) <= aoeDistance;
        });

        enemiesInRange.forEach(targetEnemy => {
            targetEnemy.props.health -= damage;

            if (targetEnemy.props.health > 0) {
                this.createHealthBar(targetEnemy);
            } else {
                this.destroyEnemy(targetEnemy, tower);
            }
        });
    }

    createHealthBar(enemy) {
        const barWidth = 30;
        const barHeight = 5;
        const barX = enemy.x - barWidth/2;
        const barY = enemy.y - enemy.displayHeight/2 - 10;
        const health = Math.max(enemy.props.health, 0);
        const fullHealth = ENEMIES_CONFIG[enemy.props.type].fullHealth;
        
        // Create health bar container
        const healthBar = this.scene.add.container(enemy.x, barY);
        
        // Background bar (red)
        const background = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0xe83829);
        
        // Health fill (green)
        const healthFill = this.scene.add.rectangle(0, 0, barWidth, barHeight, 0x00ff00);
        
        // Position the fill relative to background
        if (health === 0) {
            healthFill.width = 0;
        } else {
            healthFill.width = (health / fullHealth) * barWidth;
        }

        healthBar.add([background, healthFill]);
        this.scene.physics.world.enable(healthBar);
        healthBar.body.setVelocity(enemy.body.velocity.x, enemy.body.velocity.y);

        this.scene.tweens.add({
            targets: healthBar,
            delay: 1000,
            alpha: 0,
            onComplete: () => {
                healthBar.destroy();
            } 
        });
    }

    destroyEnemy(enemy, tower) {
        const dieX = enemy.x;
        const dieY = enemy.y;
        const type = enemy.props.type;
        const sprite = enemy.texture.key;
        const firstFrame = enemy.texture.firstFrame;
        const velocX = enemy.body.velocity.x;
        const velocY = enemy.body.velocity.y;

        // Add some Gold
        const drop = Phaser.Math.Between(ENEMIES_CONFIG[type].dropLow, ENEMIES_CONFIG[type].dropHigh) * 5;

        // Show the Gold
        const cashDrop = this.scene.add.image(dieX, dieY, 'gold').setScale(0.5);
        const angle = Phaser.Math.Angle.Between(tower.x, tower.y, dieX, dieY);

        // Calculate end position (100px away from original position in the calculated direction)
        const endX = dieX + Math.cos(angle) * 50;
        const endY = dieY + Math.sin(angle) * 50;

        // Get coords of Gold Interface
        const cam = this.scene.cameras.main;
        
        // Animate the cash drop moving to the new position
        this.scene.tweens.add({
            targets: cashDrop,
            x: endX,
            y: endY,
            duration: 500,
            ease: 'Bounce',
            onComplete: () => {
                cashDrop.postFX.addGlow();
                this.scene.tweens.add({
                    targets: cashDrop,
                    x: 1300 + cam.scrollX,
                    y: 100 + cam.scrollY,
                    alpha: 0,
                    duration: 500,
                    onComplete: () => {
                        cashDrop.destroy();
                        this.scene.UIScene.addGold(drop);
                        this.scene.UIScene.interfaceManager.updateTowerAvail();
                    }
                });
            }
        });
        
        enemy.destroy();
        
        const deadEnemy = this.scene.add.sprite(dieX, dieY, sprite, firstFrame);
        deadEnemy.play(`${type}-die`);
        
        this.scene.tweens.add({
            targets: deadEnemy,
            delay: 5000,
            duration: 2000,
            alpha: 0,
            onComplete: () => {
                deadEnemy.destroy();
            }
        });

        this.following[tower.id] = null;
    }

    createAnims() {
        this.scene.anims.create({
            key: 'gunfire',
            frames: this.scene.anims.generateFrameNumbers('ammo', {
                start:0,
                end:2
            }),
            framerate: 15,
            repeat: -1
        });
        this.scene.anims.create({
            key: 'gun-level1-fire',
            frames: this.scene.anims.generateFrameNumbers('towers', { 
                start: 0, 
                end: 1, 
            }),
            frameRate: 15,
            repeat: 6,
            yoyo: true
        });
        this.scene.anims.create({
            key: 'gun-level2-fire',
            frames: this.scene.anims.generateFrameNumbers('towers', { 
                start: 2, 
                end: 3, 
            }),
            frameRate: 15,
            repeat: 10,
            yoyo: true
        });
        this.scene.anims.create({
            key: 'gun-level3-fire',
            frames: this.scene.anims.generateFrameNumbers('towers', { 
                start: 4, 
                end: 5, 
            }),
            frameRate: 15,
            repeat: 15,
            yoyo: true
        });
        this.scene.anims.create({
            key: 'cannon-level1-fire',
            frames: this.scene.anims.generateFrameNumbers('towers', {
                start: 11,
                end: 10
            }),
            frameRate: 5,
            repeat: 0
        });
        this.scene.anims.create({
            key: 'flamethrower',
            frames: this.scene.anims.generateFrameNumbers('towers', {
                start: 23,
                end:25
            }),
            framerate: 4,
            repeat: -1
        })
    }

}