using Godot;
using System;

public partial class game : Node2D
{
	private Node _lasers;
	
	private player _player;
	
	private Node _asteroids;
	
	private wavecontroller _waveController;
	
	private CenterContainer _pauseMenu;
	
	private Control _pauseControl;

	private Node _friendlies;

	private Node _enemies;

	private Node _ships;

	private Control _hud;

	private Label _scoreLabel;

	private Label _healthLabel;

	private Label _flightAssistLabel;

	private Label _waveCounterLabel;

	private hud _h;
	
	private int _score;


	private readonly PackedScene _asteroidScene = GD.Load<PackedScene>("res://scenes/entities/asteroid.tscn");


	public override void _Ready()
	{
		_waveController = GetNode<wavecontroller>("WaveController");
		_hud = GetNode<Control>("UI/HUD");
		_scoreLabel = GetNode<Label>("UI/HUD/Layout/Score");
		_flightAssistLabel = GetNode<Label>("UI/HUD/Layout/FlightAssist");
		_pauseMenu = GetNode<CenterContainer>("UI/PauseControl/PauseMenu");
		_pauseControl = GetNode<Control>("UI/PauseControl");
		
		//HealthLabel = GetNode<Label>("UI/HUD/Health");
		_asteroids = GetNode<Node>("Asteroids");

		_lasers = GetNode<Node>("Lasers");
		_ships = GetNode<Node>("WaveController/Ships");
		_enemies = GetNode<Node>("WaveController/Ships/Enemy");
		_friendlies = GetNode<Node>("WaveController/Ships/Friendly");
		_player = GetNode<player>("WaveController/Ships/Friendly/Player");

		NewWave();
		
		//var p = new player();
		//p.LaserShot += OnPlayerLaserShot;	
	}

	private void SetupAISignals()
	{
		//AI fighter signals
		foreach (Node node in _enemies.GetChildren())
		{
			if (node is not ai_fighter ai) continue;
			//GD.Print("Connected laser signal for: ", ai.Name);
			ai.LaserShot += OnAILaserShot;
			ai.OnDeath += OnAIDeath;
		}
		
		foreach (Node node in _friendlies.GetChildren())
		{
			switch (node)
			{
				case player:
					continue;
				case ai_fighter ai:
					if (ai.SignalsConnected) break;
					//GD.Print("Connected laser signal for: ", ai.Name);

					ai.LaserShot += OnAILaserShot;
					ai.OnDeath += OnAIDeath;
					ai.SignalsConnected = true;
					break;
			}
		}
	}

	private void NewWave()
	{
		_waveController.CurrWave++;
		_waveController.StartWave();
		UpdateWaveCounterLabel();
		SetupAISignals();

		if (_waveController.CurrWave % 2 == 0)
		{
			_player.HealShip(100); // heal ship by 100 at the start of each 2nd round
		}
	}
	
	public override void _Process(double delta)
	{
		if (Input.IsActionJustPressed("reset"))
		{
			GetTree().ReloadCurrentScene();
		}

		if (Input.IsActionJustPressed("toggle_fa"))
		{
			UpdateFALabel();
		}
		
		 //AUTO SPAWN AFTER CLEAR
		if (_asteroids.GetChildCount() == 0)
		{
			Random rand = new Random();
			for (int i = 0; i < rand.Next(1, 5); i++)
			{
				SpawnAsteroid(new Vector2(rand.Next(10, 800), rand.Next(10, 800)), (int)asteroid.AsteroidSize.LARGE);
			}
		}

		if (_enemies.GetChildCount() == 0)
		{
			NewWave();
		}
		
		//if enemies == 0 -> spawn new wave, connect signals for new ships
		
	}

	private void SpawnAsteroid(Vector2 position, int size)
	{
		var a = new asteroid();
		a = _asteroidScene.Instantiate<asteroid>();
		a.GlobalPosition = position;
		a.Size = (asteroid.AsteroidSize)size;
		a.Exploded += OnAsteroidExploded;
		_asteroids.CallDeferred("add_child", a);
	}

	private void UpdateScoreLabel(int score)
	{
		/*var h = new hud();
		GD.Print(h.Score);
		h.Score.Text = "SCORE: " + score.ToString();
		GD.Print(h.Score.Text);*/

		_scoreLabel.Text = "SCORE: " + score.ToString();
	}

	private void UpdateHealthLabel(int health)
	{
		_healthLabel = GetNode<Label>("UI/HUD/Layout/Health");
		_healthLabel.Text = "HEALTH: " + health.ToString();
	}

	private void UpdateFALabel()
	{
		// Bit of a hacky implementation I think, but it works.
		if (_flightAssistLabel.Text == "FA: OFF"){_flightAssistLabel.Text = "FA: ON";}
		else if (_flightAssistLabel.Text == "FA: ON"){_flightAssistLabel.Text = "FA: OFF";}
	}

	private void UpdateWaveCounterLabel()
	{
		_healthLabel = GetNode<Label>("UI/HUD/Layout/WaveCounter");
		_healthLabel.Text = "WAVE: " + _waveController.CurrWave.ToString();
	}

//Signals and Connections
	private void OnAILaserShot(Area2D laser)
	{
		_lasers.AddChild(laser);
	}

	private void OnPlayerLaserShot(Area2D laser)
	{
		
		_lasers.AddChild(laser);
		//GD.Print(laser.Position);
		//GD.Print(_player.Position);
	}

	private void OnPlayerHealthUpdate(int health)
	{
		UpdateHealthLabel(health);
	}

	private void OnPlayerDeath()
	{
		GetTree().Paused = true;
		GetNode<game_over>("UI/PauseControl/GameOver").Visible = true;
		GetNode<AudioStreamPlayer2D>("UI/PauseControl/GameOver/ExplodeSFX").Play();
	}

	private void OnAIDeath(int factionInt)
	{
		ship.ShipFaction faction = (ship.ShipFaction)factionInt;
		switch (faction)
		{
			case ship.ShipFaction.ENEMY:
				_score += 500;
				break;
			
			case ship.ShipFaction.FRIENDLY:
				_score -= 150;
				if (_score < 0) _score = 0;
				break;
			
			case ship.ShipFaction.ACE:
				_score += 1000;
				break;
		}
		UpdateScoreLabel(_score);
	}

	private void SafeReloadScene()
	{
		GD.Print("Reloading scene");
		GetTree().ReloadCurrentScene();
	}

	private void OnAsteroidExploded(Vector2 pos, int size, ship shooter)
	{
		//GD.Print($"DEBUG: Asteroid exploded at {pos}, size: {size}");
		
		switch (size)
		{
			case 0:
			{
				for (int i = 0; i < 2; i++){
					SpawnAsteroid(pos, (int)asteroid.AsteroidSize.MEDIUM);
				}
				if (shooter is not player) return;
				_score += 60;
				break;
			}
			case 1:
			{
				for (int i = 0; i < 2; i++){
					SpawnAsteroid(pos, (int)asteroid.AsteroidSize.SMALL);
				}
				if (shooter is not player) return;
				_score += 40;
				break;
			}
			case 2:
				if (shooter is not player) return;
				_score += 20;
				break;
		}
		GD.Print(_score);
		UpdateScoreLabel(_score);
	}
}


