using Godot;
using System.Collections;
using System.Collections.Generic;
using Godot.Collections;

namespace Rokojori
{
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCGroundReset.svg")]
  public partial class Grounding:CharacterControllerAction
  {
    [Export]
    public GroundingType groundingType;

    bool _grounded = false;

    public new bool isGrounded => _hasGroundedOverwrite ? _groundedOverwriteValue : _grounded;

    bool _currentlyGrounded = false;

    public bool isCurrentlyGrounded => _currentlyGrounded;

    [Export]
    public Action onGrounded;

    [Export]
    public Action onUngrounded;

    [Export]
    public Action onCurrentlyGrounded;

    [Export]
    public Action onCurrentlyUngrounded;

    [Export]
    public float keepGroundedDuration = 0.1f;

    [ExportGroup( "Velocity Resetting" )]
    [Export]
    public bool resetVelocityWhenGrounded = true;

    bool _hasGroundedOverwrite = false;
    bool _groundedOverwriteValue = false;

    [ExportGroup( "Debugging")]    
    
    [Export]
    public bool outputDebugInfo = false;

    [Export]
    public bool currentlyGrounded = false;

    [Export]
    public bool grounded = false;

    [Export]
    public Node groundedCollider;

    [Export]
    public Node3D groundedPositionTarget;




    protected List<CollisionData> _collisionData = CollisionData.ForMaxHits( 1 );

    public CollisionData collisionData => _grounded ? null : _collisionData[ 0 ];

    float _durationSinceLastGrounded = -1;
    CollisionData _lastGroundedCollision = new CollisionData();

    public void ApplyUngroundedOverwrite()
    {
      _hasGroundedOverwrite = true;
      _groundedOverwriteValue = false;
    }

    protected override void _OnTrigger()
    {
      _hasGroundedOverwrite = false;

      var cg = _currentlyGrounded;
      var g = _grounded;

      _currentlyGrounded = GroundingType.IsGrounded( this, _collisionData );

      if ( cg != _currentlyGrounded )
      {
        if ( _currentlyGrounded )
        {
          onCurrentlyGrounded?.Trigger();
        }
        else
        {
          onCurrentlyUngrounded?.Trigger();
        }
      }

      if ( _currentlyGrounded )
      {
        _lastGroundedCollision.CopyFrom( _collisionData[ 0 ] );
        _durationSinceLastGrounded = 0;
      }

      _grounded = _currentlyGrounded || _durationSinceLastGrounded < keepGroundedDuration;

      if ( g != _grounded )
      {
        if ( _grounded )
        {
          onGrounded?.Trigger();
        }
        else
        {
          onUngrounded?.Trigger();
        }
      }

      _durationSinceLastGrounded += controller.delta;

      if ( outputDebugInfo )
      {
        currentlyGrounded = _currentlyGrounded;
        grounded = _grounded;        
        groundedCollider = _collisionData[ 0 ].collider;

        if ( IsInstanceValid( groundedPositionTarget ) )
        {
          groundedPositionTarget.GlobalPosition = _lastGroundedCollision.position;
        }
      }

      if ( ! isGrounded || ! resetVelocityWhenGrounded )
      {
        return;
      }


      // for ( int i = 0; i < resetBlockers.Length; i++ )
      // {
      //   if ( resetBlockers[ i ].HasActiveForces() )
      //   {
      //     return;
      //   }
      // }
      
      
      SetVelocity( Vector3.Zero );
      
    }

    
  }
}