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

namespace Rokojori
{
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCJump.svg")]
  public partial class Jump:CharacterControllerAction
  {
    [Export]
    public Sensor button;

    [Export]
    public Action onJump;

    [ExportGroup( "Jump Impulse")]    

    [Export]
    public float jumpImpulseStrength;

    [Export( PropertyHint.Range, "0,100" )]
    public float velocityToJumpDirection = 0.5f;
    
    [Export]
    public float velocityTresholdForJumpDirection = 1f;


    [ExportGroup( "Air Control")]

    [Export]
    public Curve airControlCurveStrength = MathX.Curve( 1, 0 );

    [Export]
    public float airMaxControlStrength;

    [Export]
    public float maxAirControlDuration;
    
    float jumpedDuration;

    bool canJump = false;

    bool jumpPressing = false;

    bool needsToRelease = false;

    bool inAir = false;
    float airStart = 0;

    public bool IsJumping()
    {
      return inAir;
    }

    public float GetAirTime()
    {
      return airStart == -1 ? 0 : ( TimeLine.osTime - airStart );
    }

    protected override void _OnTrigger()
    { 
      if ( body.IsOnFloor() )
      {
        if ( inAir )
        {
          inAir = false;
          airStart = -1;
        }

        if ( jumpPressing )
        {
          jumpPressing = false;
          needsToRelease = true;
        }
      }

      if ( ! ( jumpPressing || body.IsOnFloor() ) )
      {
        return;
      }

      if ( ! button.isActive )
      {
        jumpPressing = false;
        needsToRelease = false;
        return;
      }

      if ( needsToRelease )
      {
        return;
      }

      if ( ! jumpPressing )
      {
        jumpPressing = true;
        jumpedDuration = 0;
        inAir = true;
        airStart = TimeLine.osTime;

        Trigger( onJump );
        
        var jumpDirection = Vector3.Up * jumpImpulseStrength;

        if ( body.Velocity.Length() > velocityTresholdForJumpDirection )
        {
          var xz = body.Velocity;
          xz.Y = 0;
          // xz = xz.Normalized();

          jumpDirection += xz * velocityToJumpDirection;
        }

        SetVelocity( jumpDirection );

        return;

      }

      jumpedDuration += controller.delta;

      canJump = jumpedDuration < maxAirControlDuration;


      if ( canJump )
      {
        var jumpStrengthMultiply = airControlCurveStrength.Sample( jumpedDuration / maxAirControlDuration );
        AddVelocity( Vector3.Up * airMaxControlStrength * jumpStrengthMultiply );
      }

      
    }
  }
}