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


namespace Rokojori
{  
  [Tool]
  [GlobalClass]
  public partial class ThirdPersonCamera:VirtualCamera3D
  {
    [Export]
    public Node3D target;

    [ExportGroup("Yaw")]
    
    [Export]
    public float yawSpeed;

    [Export]
    public Sensor yawPositiveAxis;

    [Export]
    public Sensor yawNegativeAxis;

    
    [Export]
    public float yaw = 0;

    [Export]
    public float yawSmoothingDuration = 0.1f;

    Smoother yawSmoother = new Smoother();

    [ExportGroup("Pitch")]

    [Export]
    public float pitchSpeed;

    [Export]
    public Sensor pitchPositiveAxis;

    [Export]
    public Sensor pitchNegativeAxis;

    [Export]
    public bool pitchIsRelative = false;

    [Export]
    public float pitch = 0; 
    
    [Export]
    public float minPitch = -10;

    [Export]
    public float maxPitch = 80;

    [Export]
    public float pitchSmoothingDuration = 0.1f;

    Smoother pitchSmoother = new Smoother();    

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

    [Export]
    public float distanceScale = 1;

    [ExportGroup("Offset")]
    [Export]
    public Vector3 offset;

    Smoother distanceSmoother = new Smoother();

    float smoothedYaw      = 0;
    float smoothedPitch    = 0;
    float smoothedDistance = 0;


    public override void _Process( double delta )
    {
      if ( target == null )
      {
        return;
      }

      var yawAxis   = Sensors.PolarAxis( yawNegativeAxis, yawPositiveAxis );
      var pitchAxis = Sensors.PolarAxis( pitchNegativeAxis, pitchPositiveAxis );

      
      yaw += yawAxis * yawSpeed * (float)delta;      
      // yaw = MathX.Repeat( yaw, 360f );

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

          
      if ( Mathf.Abs( yaw - smoothedYaw ) > 180 )
      {
        if ( yaw > smoothedYaw )
        {
          smoothedYaw += 360;
        }
        else if ( yaw < smoothedYaw )
        {
          smoothedYaw -= 360;
        }
      }

      smoothedYaw = yaw;
      smoothedPitch = pitchSmoother.SmoothForDuration( smoothedPitch, pitch, pitchSmoothingDuration, (float) delta );

      // RJLog.Log( "Pitch", smoothedPitch );

      // smoothedYaw = yaw;
      // smoothedPitch = pitch;
      var distance = distanceForPitch.Sample( MathX.NormalizeClamped( pitch, minPitch, maxPitch ) ) * distanceScale;

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

      LookAt( target.GlobalPosition + offset, Vector3.Up, true );

      

    }

    
  }
}