using Godot;

public partial class ship : CharacterBody2D
{
    public enum ShipType { FIGHTER, INTERCEPTOR, GUARDIAN }
    
    public enum ShipFaction {PLAYER, FRIENDLY, ENEMY, ACE}

    [Signal]
    public delegate void LaserShotEventHandler(Area2D laser);

    //[Export]
    //public Vector2 ScreenSize;
    [Export]
    public int Health { get; set; }
    [Export]
    public int MaxHealth { get; set; }
    [Export]
    public int MaxSpeed { get; set;}
    [Export]
    public int MainSpeed { get; set; }
    [Export]
    public int StrafeSpeed { get; set; }
    [Export]
    public float RotationSpeed { get; set; }
    [Export]
    public int Damage {get; set; }
    [Export]
    public float FireCooldown { get; set; }
    [Export]
    public ShipType Type;
    [Export]
    public ShipFaction Faction;
    [Export]
    public float StatModifier = 1f;

    protected Sprite2D Sprite = new Sprite2D();

    protected Node2D LaserSpawn;
    
    protected float FireTimer = 0f;

    protected string SpritePath;

    protected int RotationDirection;
    
    protected readonly PackedScene LaserScene = GD.Load<PackedScene>("res://scenes/entities/laser.tscn");


    protected virtual void ShootLaser()
    {
        Laser laser = LaserScene.Instantiate<Laser>();
        laser.Position = LaserSpawn.GlobalPosition + -Transform.Y * 25f;
	    laser.Shooter = this;
        laser.Rotation = Rotation;
        GetNode<AudioStreamPlayer2D>("LaserSFX").Play();
        EmitSignal(SignalName.LaserShot, laser);
    }

    public void SetupVisual()
    {
        Sprite = GetNode<Sprite2D>("ShipSprite");
		SpritePath = ""; // Have to initialise as "" because of switch statements

		if (Faction == ShipFaction.PLAYER)
        {
            switch (Type)
		    {
			    case ShipType.FIGHTER:
			    SpritePath = "res://assets/Ships/Fighters/Player/Fighter/";
			    break;
    
			    case ShipType.INTERCEPTOR:
			    SpritePath = "res://assets/Ships/Fighters/Player/Interceptor/";
			    break;

			    case ShipType.GUARDIAN:
			    SpritePath = "res://assets/Ships/Fighters/Player/Guardian/";
			    break; 
		    }
        }
        else if (Faction == ShipFaction.FRIENDLY)
        {
            switch (Type)
            {
			    case ShipType.FIGHTER:
			    SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyFighter.png/";
			    break;
    
			    case ShipType.INTERCEPTOR:
			    SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyInterceptor.png/";
			    break;

			    case ShipType.GUARDIAN:
			    SpritePath = "res://assets/Ships/Fighters/Friendly/friendlyGuardian.png/";
			    break;                
            }
        }
        
        else if (Faction == ShipFaction.ENEMY)
        {
            switch (Type)
            {
            	case ShipType.FIGHTER:
			    SpritePath = "res://assets/Ships/Fighters/Enemy/enemyFighter.png/";
			    break;
    
			    case ShipType.INTERCEPTOR:
			    SpritePath = "res://assets/Ships/Fighters/Enemy/enemyInterceptor.png/";
			    break;

			    case ShipType.GUARDIAN:
			    SpritePath = "res://assets/Ships/Fighters/Enemy/enemyGuardian.png/";
			    break;
            }
        }
        else if (Faction == ShipFaction.ACE)
        {
            switch (Type)
            {
                case ShipType.FIGHTER:
			    SpritePath = "res://assets/Ships/Fighters/Ace/aceFighter.png/";
			    break;
    
			    case ShipType.INTERCEPTOR:
			    SpritePath = "res://assets/Ships/Fighters/Ace/aceInterceptor.png/";
			    break;

			    case ShipType.GUARDIAN:
			    SpritePath = "res://assets/Ships/Fighters/Ace/aceGuardian.png/";
			    break;
            }
        }
        if (Faction == ShipFaction.ENEMY || Faction == ShipFaction.FRIENDLY)
        {
            Sprite.RotationDegrees = 180;
        }
        else
        {
            Sprite.RotationDegrees = 0;
        }
    }

    protected void SetShipStats()
    {
        switch (Type)
        {
            case ShipType.FIGHTER:
				Health = (int)(100 * StatModifier);
				MaxSpeed = (int)(300 * StatModifier);
				MainSpeed = (int)(20 * StatModifier);
				StrafeSpeed = (int)(10 * StatModifier);
				RotationSpeed = 2f * StatModifier;
				MaxHealth = (int)(100 * StatModifier);
				Damage = (int)(30 * StatModifier);
				FireCooldown = 0.6f * StatModifier;
            break;

            case ShipType.INTERCEPTOR:
				Health = (int)(75 * StatModifier);
				MaxSpeed = (int)(450 * StatModifier);
				MainSpeed = (int)(35 * StatModifier);
				StrafeSpeed = (int)(15 * StatModifier);
				RotationSpeed = 4f * StatModifier;
				MaxHealth = (int)(75 * StatModifier);
				Damage = (int)(10 * StatModifier);
				FireCooldown = 0.3f * StatModifier;
            break;

            case ShipType.GUARDIAN:
				Health = (int)(200 * StatModifier);
				MaxSpeed = (int)(200 * StatModifier);
				MainSpeed = (int)(15 * StatModifier);
				StrafeSpeed = (int)(7 * StatModifier);
				RotationSpeed = 1.5f * StatModifier;
				MaxHealth = (int)(200 * StatModifier);
				Damage = (int)(50 * StatModifier);
				FireCooldown = 1.1f * StatModifier;
            break;
        }
    }

    public virtual void ShipDamage(int damage)
    {
        Health -= damage;
        if (Health <= 0)
        {
	        Health = 0;
	        Explode();
        }
        //GD.Print(Name, " health: ", Health);
        GetNode<AudioStreamPlayer2D>("DamageSFX").Play();
        
    }

    protected virtual void Explode()
    {
	    //GD.Print(Name, " exploded");
	    QueueFree();
    }

    public override void _Ready()
    {
        //ScreenSize = GetViewportRect().Size;
        LaserSpawn = GetNode<Node2D>("LaserSpawn");
    }

    public override void _PhysicsProcess(double delta)
    {
        // Common movement logic for all ships
        Rotation += RotationDirection * RotationSpeed * (float)delta;
        Velocity.LimitLength(MaxSpeed);
        
        MoveAndSlide();
    }
}
