
using System;
using Godot;


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

    [Export]
    public Node targetNode;

    [Export]
    public string targetMemberPath;

    [Export]
    public float endValue;

    [Export]
    public Duration duration;

    [Export]
    public Curve curve;

    [ExportGroup( "Editor Testing")]
    [Export]
    public bool forceStartValue = false;
    
    [Export]
    public float forcedStartValue = 0f;

    public void OnAnimatorStart(){}
    public void OnAnimatorEnd(){}
    public void OnAnimatorCancel(){}

    int _actionID = -1;
    int _timeID = -1;


    
    public static float GetTargetValue( GodotObject go, string targetMember, float alternative = 0 )
    {
      var path = targetMember.Split( "/" );
      var prop = path[ path.Length - 1 ];

      var target = ReflectionHelper.GetMemberByPath<object>( go, path, false );

      return target == null ? alternative : ReflectionHelper.GetValue<float>( target, prop );

    }

    public static void SetTargetValue( GodotObject go, string targetMember, float value )
    {
      var path = targetMember.Split( "/" );
      var prop = path[ path.Length - 1 ];

      var target = ReflectionHelper.GetMemberByPath<object>( go, path, false );

      if ( target == null )
      {
        return;
      }

      try
      {
        ReflectionHelper.SetValue( target, prop, value ); 
      }
      catch ( Exception e )
      {
        try
        {
          ReflectionHelper.SetValue( target, prop, (int)value ); 
        }
        catch ( Exception ex )
        {
          
      }
      }
     
      
    }

    protected override void _OnTrigger()
    {
      this.LogInfo( "Started Float Tween" );
      

      // if ( Engine.IsEditorHint() )
      // {
      //   return;
      // }

      if ( _actionID != -1 )
      {
        CancelAction( _actionID );
      }

      _actionID = DispatchStart();
      
       var target = this.target != null ? this.target : targetNode;

      // var startValue = ReflectionHelper.GetValue<float>( target, targetMember );
      var startValue = GetTargetValue( target, targetMemberPath );

      if ( forceStartValue && Engine.IsEditorHint() )
      { 
        startValue = forcedStartValue;
      }


      
     

      AnimationManager.StartAnimation( this, target, targetMemberPath );

      this.LogInfo( "Start Value Float Tween", HierarchyName.OfAny( target ), target.GetType().Name, targetMemberPath, ">>", startValue );

      _timeID = TimeLineManager.ScheduleSpanWith( duration,
        ( span, type )=>
        {         

          // this.LogInfo( "Update Float Tween", startValue );
          if ( span.id != _timeID )
          {
            return;
          }

          if ( ! AnimationManager.IsAnimating( this, target, targetMemberPath ) )
          {
            return;
          }

          var phase = span.phase;

          if ( curve != null )
          {
            phase = curve.Sample( phase );
          }

          var value = Mathf.Lerp( startValue, endValue, phase );

          // this.LogInfo( "Updating Float Tween", "phase:", phase, "value:", value, target );

          // ReflectionHelper.SetValue( target, targetMember, value );
          // target._Set( targetMember, value );    
          SetTargetValue( target, targetMemberPath, value );

          if ( type == TimeLineSpanUpdateType.End )
          {   
            // this.LogInfo( "End Float Tween", endValue );  

            SetTargetValue( target, targetMemberPath, value );    
            AnimationManager.EndAnimation( this, target, targetMemberPath );
            DispatchEnd( _actionID );
            _actionID = -1;
            _timeID = -1;
          }
        },

        this
      ).id;
    }

  }
}