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

namespace Rokojori
{  
  public enum SplinePointTangentMode
  {
    Automatic,
    Custom
  }

  [System.Serializable]
  public class Tangent
  {
    [Export]
    public Node3D node3D;
    [Export( PropertyHint.Range, "0,2" )]
    public float weight = 0.5f;
  }

  [Tool]
  [GlobalClass]
  public partial class SplinePoint : Node3D
#if TOOLS 
 , GizmoDrawerWithHandles
#endif

  {

#if TOOLS
    
    
    [ExportGroup("Editor")]
    [Export]
    public float editorSplinePointSize = 0.1f;

    public void DrawGizmo( EditorNode3DGizmoPlugin gizmoPlugin, EditorNode3DGizmo gizmo )
    {
      gizmo.Clear();

      
      var mesh = new SphereMesh();
      var size = editorSplinePointSize;
      mesh.Radius = size;
      mesh.Height = size * 2f;

      var transform = new Transform3D();
      transform.Basis = Basis.Identity;
      transform.Origin = Vector3.Zero;

      var material = gizmoPlugin.GetMaterial( "main", gizmo );
            
      
      gizmo.AddMesh( mesh, material, transform );

      gizmo.AddHandles( new Vector3[]{ Vector3.Zero }, material, new int[]{} );

    }

    public string GetHandleName( EditorNode3DGizmo gizmo, int handleId, bool secondary )
    {
      return "";
    }

    Vector3 startDragPosition = Vector3.Zero;
    public Variant GetHandleValue( EditorNode3DGizmo gizmo, int handleId, bool secondary )
    {
      startDragPosition = GlobalPosition;
      return Variant.From( GlobalPosition );
    }

    public void SetHandle( EditorNode3DGizmo gizmo, int id, bool secondary, Camera3D camera, Vector2 point )
    {
      var xzPlane = new Godot.Plane( Vector3.Up, startDragPosition );
      var cameraDirection = camera.ProjectLocalRayNormal( point );
      var intersection = xzPlane.IntersectsRay( camera.GlobalPosition, cameraDirection );

      if ( intersection == null )
      {
        return;
      }

      GlobalPosition = (Vector3) intersection;

    } 

    public void CommitHandle( EditorNode3DGizmo gizmo, int id, bool secondary, Variant restore, bool cancel )
    {
      
    }

#endif

    
    [Export]
    public float twist = 0;
    
    [Export]
    public SplinePointTangentMode tangentMode;

    [Export]
    public Node3D tangentBefore;
    [Export( PropertyHint.Range, "0,2" )]
    public float tangentBeforeWeight = 1;

    [Export]
    public Node3D tangentNext;
    [Export( PropertyHint.Range, "0,2" )]
    public float tangentNextWeight = 1;

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

    [Export( PropertyHint.Range, "0,3")]
    public float tangentScale = 1f;

    [Export( PropertyHint.Range, "0,1")]
    public float symmetricTangentLength = 0f;




  }
}