using Godot;
using Rokojori;

[Tool, GlobalClass]
public partial class AimControl : Node
{

  [Export]
  public Node3D aimSource;

  [Export]
  public Node3D characterSource;

  [Export]
  public Node3D fastAim;

  [Export]
  public float fastAimDistance = 40;

  [Export]
  public float fastScale = 1f;

  [Export]
  public float fastCharacterVelocity = 1f;


  [Export]
  public Smoothing fastPositionSmoothing;


  [Export]
  public Node3D slowAim;

  [Export]
  public float slowAimDistance = 100;

  [Export]
  public float slowScale = 1f;

  [Export]
  public float slowCharacterVelocity = 1f;

  [Export]
  public Smoothing slowPositionSmoothing;

  [Export] 
  public float yOffset = 0;

  [Export]
  public CharacterMovement characterMovement;

  [Export]
  public Node3D focusAim;

  [Export]
  public Smoothing focusSmoothing;

  [Export]
  public Pointer pointer;

  [Export]
  public Action onFocus;

  [Export]
  public Action onBlur;


  public override void _Ready()
  {
    if ( pointer == null )
    {
      return;
    }

    pointer.onPointerChange.AddAction(
      ( p )=>
      {
        if ( p == null )
        {
          this.LogInfo( "onBlur", p );
          Action.Trigger( onBlur );
        }
        else
        {
          this.LogInfo( "onFocus", p );
          Action.Trigger( onFocus );
        }
      }
    );
  }


  public override void _Process( double delta )
  {
    if ( Engine.IsEditorHint() )
    {
      return;
    }

    var cam = aimSource;
    var position = cam.GlobalPosition;
    position.Y += yOffset;
    var forward = cam.GlobalForward();
    // forward.Y = 0;

    var characterVelocity = characterMovement.smoothedMovement; 

    var localCharacterVelocity = characterSource.ToLocalDirection( characterVelocity );
    localCharacterVelocity.Z = 0;

    var worldVelocityOffset = characterSource.ToGlobalDirection( localCharacterVelocity );

    var fastAimPosition = forward * fastAimDistance + position + worldVelocityOffset * fastCharacterVelocity;
    var slowAimPosition = forward * slowAimDistance + position + worldVelocityOffset * slowCharacterVelocity;

    var fastAimSmoothPosition =  Smoothing.Apply( fastPositionSmoothing, fastAimPosition, (float)delta );
    var fastDiff = ( fastAimSmoothPosition - fastAimPosition );
    fastAim.GlobalPosition = fastAimPosition + fastDiff * fastScale;

    var slowAimSmoothPosition =  Smoothing.Apply( slowPositionSmoothing, slowAimPosition, (float)delta );
    var slowDiff = ( slowAimSmoothPosition - slowAimPosition );
    slowAim.GlobalPosition = slowAimPosition + slowDiff * slowScale;
    

    if ( pointer.pointable != null )
    {
      focusAim.GlobalPosition = Smoothing.Apply( focusSmoothing, pointer.pointable.GlobalPosition, (float)delta );
    }
  }
}
