import { Player } from '../Player.js';

export class GameScene extends Phaser.Scene {
    constructor() {
        super({ key: 'GameScene' });
        
        // Game objects references
        this.player = null;
        this.enemies = null;
        this.bullets = null;

        // Enemy bullets group
        this.enemyBullets = null;
        this.enemyMissles = null;
        
        // Game state
        this.score = 0;
        this.gameOver = false;
        
        // Mouse reticle
        this.reticle = null;
        
        // Wave system
        this.waveTimer = 0;
        this.currentWave = 0;

        // Wave configuration - easier to manage and extend
        this.waveConfig = [
            { 
                waveNumber: 0, 
                time: 0, 
                enemyTypes: [0] // Only basic enemies in wave 1
            },
            { 
                waveNumber: 1, 
                time: 20000, 
                enemyTypes: [1] // Enemies that can shoot in wave 2
            },
            { 
                waveNumber: 2, 
                time: 40000, 
                enemyTypes: [2] // Special enemies in wave 3
            },
            { 
                waveNumber: 3, 
                time: 60000, 
                enemyTypes: [3] // Special enemies in wave 3
            },
            { 
                waveNumber: 4, 
                time: 80000, 
                enemyTypes: [4] // Special enemies in wave 3
            }
        ];
    }

    preload() {
        // Load assets here (will be implemented in a later step)
        console.log('Loading assets...');

         // Load reticle image
        this.load.image('reticle', 'assets/reticle.png');

        // Load background images
        this.load.image('bg-layer1', 'assets/neon-city-bg.png');
        this.load.image('bg-layer2', 'assets/neon-city-dark-clouds2.png');
        this.load.image('bg-layer3', 'assets/neon-city-dark-clouds.png');
        this.load.image('logo', 'assets/logo.png');

        // Load Sprites
        this.load.spritesheet('player-sprite', 'assets/player-sprite.png', {
            frameWidth: 48,
            frameHeight: 48
        });
        this.load.spritesheet('enemy-sprite', 'assets/enemy-sprite.png', {
            frameWidth: 48,
            frameHeight: 48
        });

        // Load background music and sounds
        this.load.audio('bgm', 'assets/music/NeonPulse.mp3');
        this.load.audio('main-gun', 'assets/sounds/main-gun.mp3');
        this.load.audio('enemy-kill', 'assets/sounds/enemy-kill.mp3');
        this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3');
        this.load.audio('player-death', 'assets/sounds/player-death.mp3');
        this.load.audio('enemy-shoot', 'assets/sounds/enemy-shoot.mp3');
        this.load.audio('next-wave', 'assets/sounds/next-wave.mp3');
        this.load.audio('thruster', 'assets/sounds/thruster.mp3');
        this.load.audio('missle', 'assets/sounds/missle.mp3');

        // Load Fonts
        this.load.font('Space', 'assets/space-age.otf');
        
        // Create simple placeholder graphics for now
        this.createPlaceholderGraphics();
    }

    create() {
        // Set background color
        this.cameras.main.setBackgroundColor('#0a0a2a');
        
        // Create parallax backgrounds
        this.createBackgrounds();

        // Create player instance
        this.player = new Player(this);
        const { aKey, dKey } = this.player.create();
        
        // Create groups for bullets and enemies
        this.bullets = this.physics.add.group();
        this.enemyBullets = this.physics.add.group();
        this.enemies = this.physics.add.group();
        this.enemyMissles = this.physics.add.group();
        
        // Setup collision detection
        this.physics.add.overlap(this.bullets, this.enemies, this.hitEnemy, null, this);
        this.physics.add.overlap(this.player.sprite, this.enemies, this.hitPlayer, null, this);
        this.physics.add.overlap(this.player.sprite, this.enemyBullets, this.hitPlayer, null, this);
        this.physics.add.overlap(this.player.sprite, this.enemyMissles, this.hitPlayer, null, this);
        
        // Start enemy spawning
        this.time.addEvent({
            delay: 1000,
            callback: this.spawnEnemy,
            callbackScope: this,
            loop: true
        });
        
        // Create UI elements
        this.createUI();
        
        // Setup mouse input for shooting and reticle
        this.setupMouseInput();

        // Play background music
        this.bgMusic = this.sound.add('bgm', { loop: true });
        this.bgMusic.play();
    }

    createBackgrounds() {
        // Create multiple background layers with different speeds
        this.bgLayer1 = this.add.image(280, 30, 'bg-layer1').setOrigin(0.5);
        this.bgLayer2 = this.add.image(280, 30, 'bg-layer2').setOrigin(0.5);
        this.bgLayer3 = this.add.image(280, 30, 'bg-layer3').setOrigin(0.5);
        
        // Set different speeds for parallax effect (smaller = slower)
        this.bgSpeed1 = 0.2;
        this.bgSpeed2 = 0.5;
        this.bgSpeed3 = 0.8;
    }

    update(time, delta) {
        if (this.gameOver) return;
        
        // Update background positions for parallax effect
        this.updateBackgrounds();
        
        // Update wave timer
        this.waveTimer += delta;

        // Check for wave changes using the configuration array
        this.checkWaveChanges();
        
        // Get keyboard keys for player movement
        const aKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A);
        const dKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D);
        const wKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W);
        const sKey = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S);
        
        // Update player with movement controls
        this.player.update(aKey, dKey, wKey, sKey);

        // Check if enemies are off-screen and destroy them
        this.checkEnemiesOffScreen();
    }

    updateBackgrounds() {
        // Calculate speed multiplier based on player position
        // When player is at 700px (bottom), use normal speed
        // When player is at 500px (top), move faster (2x)
        const maxSpeed = 5.0; // Maximum speed multiplier
        const minSpeed = 1.0; // Minimum speed multiplier
        
        let speedMultiplier = minSpeed;
        
        if (this.player && this.player.sprite) {
            const playerY = this.player.sprite.y;
            
            // Map Y position to speed multiplier (700px = normal, 500px = max)
            if (playerY < 700) {
                speedMultiplier = minSpeed + ((700 - playerY) / (700 - 500)) * (maxSpeed - minSpeed);
            }
            
            // Ensure we don't go below minimum
            speedMultiplier = Math.max(minSpeed, speedMultiplier);
        }

        // Move background layers at different speeds with the calculated multiplier
        this.bgLayer1.y += this.bgSpeed1 * speedMultiplier;
        this.bgLayer2.y += this.bgSpeed2 * speedMultiplier;
        this.bgLayer3.y += this.bgSpeed3 * speedMultiplier;
        
        // Reset positions to create continuous scrolling effect
        if (this.bgLayer1.y > 736) {
            this.bgLayer1.y = 0;
        }
        if (this.bgLayer2.y > 1536) {
            this.bgLayer2.y = 0;
        }
        if (this.bgLayer3.y > 1536) {
            this.bgLayer3.y = 0;
        }
    }

    checkWaveChanges() {
        // Iterate through wave configurations to find which wave should start
        for (let i = 0; i < this.waveConfig.length; i++) {
            const wave = this.waveConfig[i];
            
            // If we haven't started this wave yet and the timer has passed
            if (this.waveTimer >= wave.time && this.currentWave === wave.waveNumber - 1) {
                this.startWave(wave.waveNumber);
                break; // Only start one wave per update cycle
            }
        }
    }

    setupMouseInput() {
        // Create mouse reticle as sprite (replacing the circle)
        this.reticle = this.add.sprite(0, 0, 'reticle');
        this.reticle.setOrigin(0.5);
        this.reticle.preFX.addGlow(0x00ffcc, .7);
        
        // Update reticle position with mouse
        this.input.on('pointermove', (pointer) => {
            if (this.gameOver) return;
            
            this.reticle.x = pointer.x;
            this.reticle.y = pointer.y;
        });
        
        // Shooting with left mouse button
        this.input.on('pointerdown', (pointer) => {
            if (this.gameOver) return;
            
            if (pointer.leftButtonReleased()) {
                this.shoot(pointer);
            }
        });
    }

    createPlaceholderGraphics() {
        // Create simple placeholder graphics for player, bullets and enemies
        const canvas = document.createElement('canvas');
        canvas.width = 32;
        canvas.height = 32;
        
        // Enemy (square)
        const enemyCanvas = document.createElement('canvas');
        enemyCanvas.width = 24;
        enemyCanvas.height = 24;
        
        const eCtx = enemyCanvas.getContext('2d');
        eCtx.fillStyle = '#ff3366';
        eCtx.fillRect(0, 0, 24, 24);
        
        this.textures.addCanvas('enemy', enemyCanvas);
        
        // Bullet (small circle)
        const bulletCanvas = document.createElement('canvas');
        bulletCanvas.width = 8;
        bulletCanvas.height = 8;
        
        const bCtx = bulletCanvas.getContext('2d');
        bCtx.fillStyle = '#ffff00';
        bCtx.beginPath();
        bCtx.arc(4, 4, 3, 0, Math.PI * 2);
        bCtx.fill();
        
        this.textures.addCanvas('bullet', bulletCanvas);

        // Enemy Bullet (small circle)
        const enemyBulletCanvas = document.createElement('canvas');
        enemyBulletCanvas.width = 8;
        enemyBulletCanvas.height = 8;
        
        const ebCtx = enemyBulletCanvas.getContext('2d');
        ebCtx.fillStyle = '#00ffcc';
        ebCtx.beginPath();
        ebCtx.arc(4, 4, 3, 0, Math.PI * 2);
        ebCtx.fill();
        
        this.textures.addCanvas('enemyBullet', enemyBulletCanvas);
    }

    createUI() {
        // Create score text
        this.scoreText = this.add.text(16, 16, 'Score: 0', { 
            fontSize: '28px', 
            fill: '#ffffff',
            fontFamily: 'Space, Arial'
        });
        
        this.titleText = this.add.image(500, 50, 'logo').setScale(.3).setOrigin(0.5).postFX.addGlow();
    }

    shoot(pointer) {
        // Calculate angle between player and mouse
        const angle = Phaser.Math.Angle.Between(
            this.player.sprite.x,
            this.player.sprite.y,
            pointer.x,
            pointer.y
        );
        
        // Create bullet at player position
        const bullet = this.bullets.create(this.player.sprite.x, this.player.sprite.y, 'bullet');
        
        // Set velocity based on angle and speed
        const speed = 400;
        bullet.setVelocityX(Math.cos(angle) * speed);
        bullet.setVelocityY(Math.sin(angle) * speed);
        
        // Scale bullet
        bullet.setScale(1.5);

        // Sound Effects
        this.sound.play('main-gun');
    }

    spawnEnemy() {
        // Spawn enemies at random x position within game width (800px)
        const x = Phaser.Math.Between(20, 580);

        // Calculate texture range with minimum of 0
        const minTexture = Math.max(0, this.currentWave - 2);
        const maxTexture = this.currentWave;
        
        // Ensure we don't get negative values
        const texture = Phaser.Math.Between(minTexture, maxTexture);

        const enemy = this.enemies.create(x, 0, 'enemy-sprite', texture);
        
        // Randomize enemy speed
        const speed = Phaser.Math.Between(50, 150);
        enemy.setVelocityY(speed);
        
        // Apply wave-specific properties
        this.applyWaveProperties(enemy, texture);
    }

    applyWaveProperties(enemy, texture) {
        // Set the current wave number on the enemy
        enemy.waveNumber = this.currentWave;
        
        // Wave 1: Basic enemies (no shooting)
        if (this.currentWave === 0) {
            enemy.canShoot = false;
            enemy.canMissle = false;
            if (enemy.shootTimer) {
                enemy.shootTimer.remove();
                enemy.shootTimer = null;
            }
        }
        // Wave 3: Enemies with missles
        else if (this.currentWave >= 3 && texture === 3) {
            enemy.canMissle = true;
            // Only set up shooting timer if it doesn't exist yet
            if (!enemy.missleTimer) {
                enemy.missleTimer = this.time.addEvent({
                    delay: Phaser.Math.Between(1000, 3000),
                    callback: () => this.enemyMissle(enemy, texture),
                    callbackScope: this,
                    loop: true
                });
            }
        } 
        // Wave 2: Enemies that can shoot
        else if (this.currentWave >= 1 && texture > 0 && texture <= 4) {
            enemy.canShoot = true;
            enemy.canMissle = false;
            // Only set up shooting timer if it doesn't exist yet
            if (!enemy.shootTimer) {
                enemy.shootTimer = this.time.addEvent({
                    delay: Phaser.Math.Between(1000, 3000),
                    callback: () => this.enemyShoot(enemy, texture),
                    callbackScope: this,
                    loop: true
                });
            }
        }
    }

    hitEnemy(bullet, enemy) {
        bullet.destroy();
        enemy.destroy();
        this.sound.play('enemy-kill');
        
        this.score += 10;
        this.scoreText.setText('Score: ' + this.score);
    }

    hitPlayer(player, enemy) {
        // Create explosion at player's position
        const explosion = this.add.sprite(this.player.sprite.x, this.player.sprite.y, 'player-sprite', 3);
        const explosion2 = this.add.sprite(this.player.sprite.x, this.player.sprite.y, 'player-sprite', 3);
        
        // Add rotation and scaling animation
        this.tweens.add({
            targets: explosion,
            scale: 3, // Scale up to 3x
            rotation: Math.PI * 2, // Full rotation
            alpha: 0.5, // Fade out slightly
            duration: 1000,
            ease: 'Power2',
            onComplete: () => {
                explosion.destroy();
            }
        });
        this.tweens.add({
            targets: explosion2,
            scale: 3, // Scale up to 3x
            rotation: -Math.PI * 2, // Full rotation
            alpha: 0.5, // Fade out slightly
            duration: 1000,
            ease: 'Power2',
            onComplete: () => {
                explosion2.destroy();
            }
        });
        
        player.destroy();
        enemy.destroy();
        this.sound.play('player-death');
        
        this.gameOver = true;
        
        // Show game over text
        const gameOverText = this.add.text(300, 400, 'GAME OVER', { 
            fontSize: '54px', 
            fill: '#ff3366',
            fontFamily: 'Space, Arial'
        });
        gameOverText.setOrigin(0.5);
        
        this.tweens.add({
            targets: this.bgMusic,
            volume: 0,
            duration: 5000,
        });

        // Return to menu after delay
        this.time.delayedCall(5000, () => {
            // Fade camera out before returning to menu
            this.tweens.add({
                targets: this.cameras.main,
                alpha: 0, // Fade to transparent
                duration: 1000, // 1 second fade
                ease: 'Linear',
                onComplete: () => {
                    this.bgMusic.stop();
                    this.scene.start('MenuScene');
                }
            });
        });
    }

    startWave(waveNumber) {
        this.currentWave = waveNumber;
        this.sound.play('next-wave');
        
        // Add wave indicator text
        const waveText = this.add.text(300, 150, `WAVE ${waveNumber + 1}`, { 
            fontSize: '48px',
            fill: '#ffff00',
            fontFamily: 'Space, Arial'
        });
        waveText.setOrigin(0.5);
        
        // Add scaling animation
        this.tweens.add({
            targets: waveText,
            scale: 2, // Grow to double size
            duration: 1000,
            ease: 'Elastic.out', // Elastic easing for bouncy effect
            yoyo: true, // Scale back and forth
            repeat: 1 // Do the animation twice (total of 3 states)
        });
        
        // Remove text after delay
        this.time.delayedCall(2000, () => {
            waveText.destroy();
        });
        
        // Apply wave properties to all existing enemies
        this.enemies.children.iterate((enemy) => {
            this.applyWaveProperties(enemy);
        });
    }
    
    enemyShoot(enemy, texture) {
        // Only shoot if enemy can shoot and isn't destroyed
        if (!enemy.canShoot || !enemy.active) return;

        if (texture === 4) {
            const fan = [1.3, 1.5, 1.7, 1.9];
            fan.forEach((value) => {
                const bullet = this.enemyBullets.create(enemy.x, enemy.y, 'enemyBullet');
                const speed = 200;
                bullet.setVelocityX(Math.cos(value) * speed);
                bullet.setVelocityY(Math.sin(value) * speed);
                bullet.setScale(1.5);
            });

        } else if (this.currentWave >= 2 && enemy.waveNumber >= 2 && texture === 2) {
            // Shoot toward player
            const angle = Phaser.Math.Angle.Between(
                enemy.x,
                enemy.y,
                this.player.sprite.x,
                this.player.sprite.y
            );
            
            const bullet = this.enemyBullets.create(enemy.x, enemy.y, 'enemyBullet');
            const speed = 200;
            bullet.setVelocityX(Math.cos(angle) * speed);
            bullet.setVelocityY(Math.sin(angle) * speed);
            bullet.setScale(1.5);
        } else if (texture === 1) {
            const vari = Phaser.Math.Between(1,2);
            if (vari === 2) {
                // Regular straight-down shooting
                const bullet = this.enemyBullets.create(enemy.x, enemy.y, 'enemyBullet');
                bullet.setVelocityY(300); // Move straight down at 200px/s
                bullet.setScale(1.5);
            }
        }
        
        // Sound effect for enemy shooting
        this.sound.play('enemy-shoot');
    }

    enemyMissle(enemy, texture) {
        // Only shoot if enemy can shoot and isn't destroyed
        if (!enemy.canMissle || !enemy.active) return;
        
        // Check if this is wave 3 and enemy has texture 2 (special shooting)
        if (this.currentWave >= 3 && enemy.waveNumber >= 3 && texture >= 3) {
            const missle1 = this.enemyMissles.create(enemy.x, enemy.y, 'enemy-sprite', 30);
            const missle2 = this.enemyMissles.create(enemy.x, enemy.y, 'enemy-sprite', 30);

            // Initial velocity
            missle1.setVelocityX(-100).setVelocityY(-200).setAngle(135).setScale(.5);
            missle2.setVelocityX(100).setVelocityY(-200).setAngle(-135).setScale(.5);
            
            // After 500ms, change direction towards player and increase speed
            this.time.delayedCall(500, () => {
                if (missle1 && missle1.active) {
                    const angle = Phaser.Math.Angle.Between(
                        missle1.x,
                        missle1.y,
                        this.player.sprite.x,
                        this.player.sprite.y
                    );
                    
                    // Increase velocity to 300 and change direction
                    missle1.setVelocityX(Math.cos(angle) * 300);
                    missle1.setVelocityY(Math.sin(angle) * 300);
                    missle1.setAngle(Phaser.Math.RadToDeg(angle)-90);
                }
                
                if (missle2 && missle2.active) {
                    const angle = Phaser.Math.Angle.Between(
                        missle2.x,
                        missle2.y,
                        this.player.sprite.x,
                        this.player.sprite.y
                    );
                    
                    // Increase velocity to 300 and change direction
                    missle2.setVelocityX(Math.cos(angle) * 300);
                    missle2.setVelocityY(Math.sin(angle) * 300);
                    missle2.setAngle(Phaser.Math.RadToDeg(angle)-90);
                }
            });
        }
        
        // Sound effect for enemy shooting
        this.sound.play('missle');
    }

    checkEnemiesOffScreen() {
        // Destroy enemies that have gone below the screen
        this.enemies.children.iterate((enemy) => {
            if (enemy && enemy.y > 800) { // Adjust 600 to your game height as needed
                enemy.destroy();
            }
        });
    }
}