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


namespace Rokojori
{  
  [Tool]
  [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/3rdPersonCamera.svg") ]
  public partial class ThirdPersonCamera:VirtualCamera
  {
    [Export]
    public Node3D target;
    
    [Export]
    public float yaw;

    [Export]
    public float pitch;

    [Export]
    public ThirdPersonCameraSettings settings;

    // [Export]
    // public TimeLine timeLine;

    [Export]
    public CharacterController.CharacterUpdateMode updateMode = CharacterController.CharacterUpdateMode.Physics_Process;

    public override void _Process( double delta )
    {
      if ( CharacterController.CharacterUpdateMode.Process == updateMode )
      {
        _ProcessCamera( delta );
      }
    }

    public override void _PhysicsProcess( double delta )
    {
      if ( CharacterController.CharacterUpdateMode.Physics_Process == updateMode )
      {
        _ProcessCamera( delta );
      }
    }

    void _ProcessCamera( double gameDelta )
    {
      if ( Engine.IsEditorHint() )
      {
        return;
      }

      if ( target == null )
      {
        return;
      }


      // var tl = TimeLineManager.Ensure( timeLine );
      // var delta = tl.delta;
      var delta = (float) gameDelta;
      var data = settings.GetActiveDeviceData();

      var targetPosition = Smoothing.Apply( settings.targetFollowSmoothing, target.GlobalPosition, delta );


      var yawAxis   = Sensors.PolarPowerAxis( data.yawNegativeAxis, data.yawPositiveAxis, 1f, data.yawDeadZone, data.yawPower );
      var pitchAxis = Sensors.PolarPowerAxis( data.pitchNegativeAxis, data.pitchPositiveAxis, 1f, data.pitchDeadZone, data.pitchPower );

      // this.LogInfo( "YAW:", yawAxis, "PITCH:", pitchAxis ); 
      yaw += yawAxis * settings.yawSpeed * data.yawSpeed * delta;
      

      if ( data.pitchIsRelative )
      {
        pitch += pitchAxis * settings.relativePitchSpeed * data.relativePitchSpeed * delta;     
        pitch = Mathf.Clamp( pitch, settings.minPitch, settings.maxPitch );
      }
      else
      { 
        pitch = Mathf.Remap( pitchAxis, -1, 1, settings.minPitch, settings.maxPitch );
      }

      var appliedYaw = yaw;

      var smoothedYaw = Smoothing.ApplyDegrees( settings.yawSmoothing, appliedYaw, delta );

      var smoothedPitch = Smoothing.Apply( settings.pitchSmoothing, pitch, delta );

      var distance = settings.distanceForPitch.Sample( MathX.NormalizeClamped( pitch, settings.minPitch, settings.maxPitch ) ) * settings.distanceScale;

      GlobalPosition =  targetPosition + Math3D.YawPitchRotation( smoothedYaw, smoothedPitch ) * Vector3.Forward * distance;

      LookAt( targetPosition, Vector3.Up, true );

      GlobalPosition += this.GetOrientationBasedGlobalOffset( settings.offset );

    }

    
  }
}