using System;
using Cirno.Scripts.Components;
using Cirno.Scripts.Resources;
using Godot;

namespace Cirno.Scripts.Activables;

public partial class BulletEmitter : Node2D, IActivable
{
    [Export]
    public BulletResource BulletResource { get; set; }
    
    [Export]
    public bool EmitOnStart { get; set; } = false;
    
    [Export]
    public bool InvertSignal { get; private set; } = false;
    
    [Export]
    public float EmitCoolDown { get; private set; } = 0.2f;
    
    [Export] public float BurstCoolDown { get; private set; } = 2f;
    
    [Export] public float Spread { get; set; } = 0f;

    [Export] public int Count { get; set; } = 1;
    
    [Export] public float EmissionRotation { get; set; } = 0f;
    
    [Export] public float RotationSpeed { get; private set; } = 0f;
    
    [Export] public int BulletsPerBurst { get; private set; } = 1;
    
    
    [Signal]
    public delegate void StateChangedEventHandler(bool isEmitting);
    
    private BulletSpawner _bulletSpawner;

    protected bool IsEmitting = false;

    private double _emitTimer = 0f;
    
    private double _reloadTimer = 0f;
    
    private float _currentEmissionRotation = 0f;

    private int _currentBullets = 0;
    
    private bool _isReloading = false;
    
    public override void _Ready()
    {
        _bulletSpawner = GetNode<BulletSpawner>("BulletSpawner");
        
        _currentEmissionRotation = EmissionRotation;
        _currentBullets = BulletsPerBurst;
        
        if (EmitOnStart)
        {
            IsEmitting = true;
            CallDeferred(MethodName.Shoot);
        }
        EmitSignal(SignalName.StateChanged, IsEmitting);
    }

    public override void _Process(double delta)
    {
        if (!IsEmitting) return;
        
        if (_isReloading)
        {
            _reloadTimer += delta;

            if (_reloadTimer >= BurstCoolDown)
            {
                _currentBullets = BulletsPerBurst;
                _isReloading = false;
                _reloadTimer = 0f;
            }

            return;
        }

        _emitTimer += delta;

        if (_emitTimer >= EmitCoolDown)
        {
            Shoot();
            _emitTimer = 0f;
        }
    }

    public void Shoot()
    {
        _bulletSpawner.SpawnBullet(BulletResource.MakeBullet(this.GlobalPosition, Count, Spread, _currentEmissionRotation));
        
        _currentEmissionRotation += RotationSpeed;
        
        _currentBullets--;

        if (_currentBullets <= 0)
        {
            _isReloading = true;            
        }
    }
    
    public bool Activate(ActivationType activationType = ActivationType.Toggle)
    {
        switch (activationType)
        {
            case ActivationType.Open:
            case ActivationType.Enable:
                IsEmitting = !InvertSignal;
                _emitTimer = 0;
                break;
            case ActivationType.Close:
            case ActivationType.Disable:
                IsEmitting = InvertSignal;
                _emitTimer = 0;
                break;
            case ActivationType.Use:
            case ActivationType.Toggle:
                IsEmitting = !IsEmitting;
                _emitTimer = 0;
                break;
            case ActivationType.Destroy:
                break;
        }
        
        EmitSignal(SignalName.StateChanged, IsEmitting);
        return true;
    }
}