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

namespace Rokojori
{
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCMoveAndSlide.svg")]
  public partial class MoveAndSlide:CharacterControllerAction
  {
    [Export]
    public bool useStepping = false;

    [Export] 
    public float stepMaxHeight = 0.2f;

    protected override void _OnTrigger()
    {
      var body = controller.body;
      var motion = controller.body.Velocity * controller.delta;

      var collision = body.MoveAndCollide( motion, testOnly: true );

      if ( collision != null && StepUp( motion ) )
      {
        return;
      }

      controller.body.MoveAndSlide();
    }

    protected bool StepUp( Vector3 motion )
    {
      var up = Vector3.Up * stepMaxHeight;

      var hitAbove = controller.body.TestMove( controller.body.GlobalTransform, up );

      if ( hitAbove ) 
      {
        return false;
      }

      bool hitForward = controller.body.TestMove( controller.body.GlobalTransform.Translated( up ), motion );

      if ( ! hitForward )
      {
        var space = controller.body.GetWorld3D().DirectSpaceState;
        var origin = controller.body.GlobalPosition;
        var stepUpOrigin = controller.body.GlobalPosition + up;

        var downHit = space.IntersectRay(
          new PhysicsRayQueryParameters3D
          {
            From = stepUpOrigin,
            To = stepUpOrigin + Vector3.Down * ( stepMaxHeight + 0.1f ),
            CollisionMask = 1,
            CollideWithAreas = false,
            CollideWithBodies = true
          }
        );

        if ( downHit.Count == 0 )
        {
          return false;
        }

        var exactStepAmount = downHit[ "position" ].AsVector3().Y - origin.Y;

        if ( exactStepAmount > 0 && exactStepAmount <= stepMaxHeight )
        {
          controller.body.GlobalTranslate( new Vector3( 0, exactStepAmount, 0 ) );
          return true;
        }
      }

      return false;
    }
  }
}