
using System;
using Godot;


namespace Rokojori
{  
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Tween.svg")]
  public partial class TweenPosition:SequenceAction
  {
    [Export]
    public Node3D target;

    [Export]
    public Mode positionSpace = Mode.Global;

    [Export]
    public Node3D endPosition;

    public enum Mode
    {
      Global,
      Local
    }

    [Export]
    public Vector3 endOffset;

    

    [Export]
    public TweenType tweenType = new TweenTimeCurve();




    [Export]
    public bool cacheEndPositionOnStart = true;

    [Export]
    public TimeLine timeLine;


    Vector3 GetToPosition()
    {
      var toPosition = endOffset;

      if ( Mode.Global == positionSpace )
      { 
        if ( endPosition != null )
        {
          toPosition += endPosition.GlobalPosition;
        }
      }
      else
      {
        
        if ( endPosition != null )
        {
          toPosition += endPosition.Position;
        }

      }

      return toPosition;           

     
    }

    protected override void _OnTrigger()
    {
      if ( target == null )
      {
        return;
      }

      var tl = TimeLineManager.Ensure( timeLine );

      var start = tl.position;

      var fromPosition =  target.GetPosition( Mode.Global == positionSpace );
      var toPosition = GetToPosition(); 

      var sequenceID = DispatchStart(); 

      var tweenType = this.tweenType;

      if ( tweenType == null )
      {
        tweenType = TweenTimeCurve.defaultCurve;
      }      

      TimeLineManager.ScheduleSpanIn( tl, 0, tweenType.GetTweenDuration(), 
        ( span, type )=>
        {         
          if ( ! GodotObject.IsInstanceValid( target ) )
          {
            DispatchEnd( sequenceID );
            return;
          }
          
          var timeNow = tl.position;
          var elapsed = timeNow - start;

          var state = tweenType.GetTweenPhaseForPhase( span.phase );

          if ( ! cacheEndPositionOnStart )
          {
            toPosition = GetToPosition(); 
          }

          var lerpedPosition = fromPosition.Lerp( toPosition, state );

          if ( Mode.Global == positionSpace )
          {
            target.GlobalPosition = lerpedPosition;
          }
          else if ( Mode.Local == positionSpace )
          {
            target.Position = lerpedPosition;
          }

          if ( type == TimeLineSpanUpdateType.End )
          {          
            DispatchEnd( sequenceID );
          }
        }
      );
    }

  }
}