using System.Linq;
using Godot;

namespace Cirno.Scripts.Weapons;

public partial class LaserBullet : Bullet
{
    private Line2D _beam;
    private Timer _preFireTimer;
    private Timer _lethalTimer;
    private Timer _spawnDelayTimer;
    private bool _isLethal = false;
    
    public override void _Ready()
    {
        base._Ready();
        _beam = new Line2D
        {
            DefaultColor = BulletInfo.PreFireColor,
            Width = 1,
            Visible = false
        };
        AddChild(_beam);
        _beam.GlobalPosition = this.GlobalPosition;
        
        // Delay before the beam appears
        _spawnDelayTimer = new Timer { WaitTime = BulletInfo.SpawnDelay, OneShot = true };
        _spawnDelayTimer.Timeout += ShowBeam;
        AddChild(_spawnDelayTimer);
        _spawnDelayTimer.Start();
        
        FireLaser();
    }

    public void FireLaser()
    {
        Vector2 endPoint = GetLaserEndPoint(GlobalPosition, BulletInfo.Direction);

        _beam.ClearPoints();
        _beam.AddPoint(Vector2.Zero);
        _beam.AddPoint(ToLocal(endPoint));

        _preFireTimer = new Timer { WaitTime = BulletInfo.PreFireTime, OneShot = true };
        _preFireTimer.Timeout += MakeLethal;
        AddChild(_preFireTimer);
        _preFireTimer.Start();
    }

    private void ShowBeam()
    {
        _beam.Visible = true;
    }

    private void MakeLethal()
    {
        _isLethal = true;
        _beam.DefaultColor = BulletInfo.LethalColor;
        _beam.Width = 3;

        _lethalTimer = new Timer { WaitTime = BulletInfo.LethalTime, OneShot = true };
        _lethalTimer.Timeout += QueueFree; // Destroy after lethal phase
        AddChild(_lethalTimer);
        _lethalTimer.Start();
    }

    public override void RotateBullet(float degrees)
    {
        base.RotateBullet(degrees);
        
        _beam.SetPointPosition(_beam.Points.Length -1, ToLocal(GetLaserEndPoint(GlobalPosition, _direction)));
    }
    
    private Vector2 GetLaserEndPoint(Vector2 start, Vector2 direction)
    {
        var spaceState = GetWorld2D().DirectSpaceState;
        var query = PhysicsRayQueryParameters2D.Create(start, start + direction * 1000);
        query.CollisionMask = 1 << 0; // World layer
        var result = spaceState.IntersectRay(query);

        return result.Count > 0 ? (Vector2)result["position"] : start + direction * 1000;
    }
}