using Cirno.Scripts.Actors;
using Cirno.Scripts.Resources;
using Godot;
using Godot.Collections;

namespace Cirno.Scripts.AttackPatterns;

[GlobalClass]
[Tool]
public partial class CreateEmitterPattern : AttackPattern
{
    [Export] public Vector2 SpawnOffset { get; set; }
    [Export] public BulletScript Script { get; set; }
    [Export] public PackedScene Prefab { get; set; }
    [Export] public bool CreateAsChild { get; set; }

    [Export] public double LifeTime { get; set; } = 10d;

    public override IPatternMachine MakeMachine(Node parent)
    {
        return new EmitterPatternMachine(this, parent);
    }

    public class EmitterPatternMachine(CreateEmitterPattern pattern, Node parent) : IPatternMachine
    {
        private bool _active = false;
        public Node Parent => parent;
        public AutonomousBulletEmitter Emitter { get; private set; }

        public void Start()
        {
            if (parent is not Node2D parent2d)
            {
                return;
            }
            
            Emitter = pattern.CreateAsChild
                ? parent2d.CreateChild<AutonomousBulletEmitter>(pattern.Prefab,
                    parent2d.GlobalPosition + pattern.SpawnOffset)
                : parent2d.CreateSibling<AutonomousBulletEmitter>(pattern.Prefab,
                    parent2d.GlobalPosition + pattern.SpawnOffset);
            Emitter.Script = pattern.Script;
            Emitter.EmitOnStart = true;
            Emitter.LifeTime = pattern.LifeTime;

            _active = true;
            Emitter.Autonomous = !pattern.WaitForCompletion;

            Emitter.Death += EmitterOnDeath;

            Emitter.Start();
        }

        private void EmitterOnDeath()
        {
            _active = false;
            Emitter.Death -= EmitterOnDeath;
        }

        public void UpdatePattern(double delta)
        {
            if (_active)
            {
                if (pattern.WaitForCompletion)
                {
                    Emitter.Update(delta);
                }
            }
        }

        public bool IsComplete()
        {
            if (pattern.WaitForCompletion)
                return !_active;
            return _active;
        }
    }
}