
using Godot;
using System.Collections.Generic;

namespace Rokojori
{  
  [Tool][GlobalClass]
  public partial class PlaySound:Action
  {
    [Export]
    public AudioStreamPlayer3D player;
    

    [ExportGroup("Randomize Playback Position")]
    [Export]
    public bool randomizePlaybackPosition = false;
    
    [Export]
    public Duration durationPerSound;

    [Export]
    public bool generatePools = true;


    List<AudioStreamPlayer3D> players = new List<AudioStreamPlayer3D>();


    AudioStreamPlayer3D GetFreePlayer()
    {
      if ( players.Count == 0 )
      {
        players.Add( player );
      }

      var freePlayer = players.Find( p => ! p.Playing );

      if ( freePlayer != null )
      {
        return freePlayer;
      }

      var newPlayer = player.GetParent().CreateChild<AudioStreamPlayer3D>();
      newPlayer.Stream = player.Stream;
      newPlayer.VolumeDb = player.VolumeDb;
      newPlayer.MaxDb = player.MaxDb;
      newPlayer.UnitSize = player.UnitSize;
      newPlayer.AttenuationModel = player.AttenuationModel;

      players.Add( newPlayer );
      return newPlayer;

    }

    protected override void _OnTrigger()
    {
      var offset = 0f;

      var player = generatePools ? GetFreePlayer() : this.player;
      
      if ( randomizePlaybackPosition )
      {
        var random = LCG.WithSeed( networkSeed );

        var length = player.Stream.GetLength();
        var numOffsets = Mathf.FloorToInt( length / durationPerSound.GetDurationInSeconds() );
        var randomIndex = random.IntegerExclusive( numOffsets );
        offset = randomIndex * durationPerSound.GetDurationInSeconds();

        // this.LogInfo( "Offset", numOffsets, randomIndex, offset );
      }

      player.Play( offset );

      if ( randomizePlaybackPosition )
      {
        var tl = TimeLineManager.Ensure( durationPerSound.timeLine );

        var start = tl.position;

        TimeLineManager.ScheduleSpanIn( durationPerSound.timeLine, 0, durationPerSound.GetDurationInSeconds(), 
        ( span, type )=>
        {         
          var timeNow = tl.position;
          var elapsed = timeNow - start;

          var phase = span.phase;
         
          if ( type == TimeLineSpanUpdateType.End )
          {          
            player.Stop();
            player.Playing = false;
          }
        }
      );
      }
    }
  }
}