
using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  [Tool][GlobalClass, Icon("res://addons/rokojori_action_library/Icons/PlayParticles.svg")]
  public partial class PlayParticles:Action
  {
    [Export]
    public GpuParticles3D particles3D;

    [Export]
    public bool usePooling = false;

    [Export]
    public float godotFinishedReporingBugOffset = 0.2f;

    [Export]
    public TimeLine timeLine;

    List<GpuParticles3D> _pool = new List<GpuParticles3D>();
    List<bool> _emitting = new List<bool>();


    protected override void _OnTrigger()
    {
      if ( ! usePooling )
      {
        particles3D.Restart();
        return;
      }

      if ( _emitting.Count == 0 )
      {
        _emitting.Add( false );
      }
      
      var p = GetFreeParticles();

      if ( p == null )
      {
        p = DuplicateParticles();
      }

      // this.LogInfo( "Using Particles", p );

      

      var index = IndexOf( p );

      _emitting[ index ] = true;

      p.OnFinishedOnce( 
        () => 
        {
          if ( godotFinishedReporingBugOffset <= 0 )
          { 
            _emitting[ index ] = false;
            return;
          }

          TimeLineManager.ScheduleEventIn( 
            timeLine, 
            godotFinishedReporingBugOffset, 
            t => _emitting[ index ] = false 
          );
        }
      );
      p.Restart();
    }

    public int IndexOf( GpuParticles3D p )
    {
      return p == particles3D ? 0 : _pool.IndexOf( p ) + 1;
    }

    public bool IsEmitting( GpuParticles3D p )
    {
      return _emitting[ IndexOf( p ) ];
    } 

    GpuParticles3D GetFreeParticles()
    {
      if ( ! IsEmitting( particles3D ) )
      {
        return particles3D;
      }

      return _pool.Find( p => ! p.Emitting );
    }

    GpuParticles3D DuplicateParticles()
    {
      this.LogInfo( "Duplicating Particles" );
      var duplicate = particles3D.Duplicate() as GpuParticles3D;
      _pool.Add( duplicate );
      particles3D.GetParent().AddChild( duplicate );
      _emitting.Add( false );
      return duplicate;
    }
  }
}