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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class ConnectionPin:Node3D
  #if TOOLS 
 , GizmoDrawer
#endif
  {
    [Export]
    public bool updateAlways = false;

    [Export]
    public Node3D root;

    [Export]
    public bool moveToMinX = false;
    
    [Export]
    public bool moveToMaxX = false;

    [Export]
    public bool moveToMinY = false;

    [Export]
    public bool moveToMaxY = false;

    [Export]
    public bool moveToMinZ = false;

    [Export]
    public bool moveToMaxZ = false;

    [Export]
    public float editorGizmoSize = 1;

    float _editorGizmoSize = 1;


#if TOOLS

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

      var center  = Vector3.Zero;
      var up      = Vector3.Up * editorGizmoSize;
      var forward = Vector3.Forward * editorGizmoSize;
      var right   = Vector3.Right * editorGizmoSize;

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

      gizmo.AddLines( 
        new Vector3[] 
        {
          center, up, 
          center, -forward,
          center, right,
          center, -right,
          right, -forward,
          -right, -forward,
          up, -forward,
          up, -right,
          up, right
        },
        material
      );
    }

    public override void _Process( double delta )
    {
      var changed = false;

      if ( editorGizmoSize != _editorGizmoSize )
      {
        _editorGizmoSize = editorGizmoSize;
        changed = true;
      }

      if ( changed )
      {
        UpdateGizmos();
      }

      if ( ! ( moveToMinX || moveToMaxX || moveToMinY || moveToMaxY || moveToMinZ || moveToMaxZ ) )
      {
        return;
      }

      if ( root == null )
      {
        RJLog.Log( "No Root!" );
        ClearFlags();
        return;
      }


      var optionalBbounds = root.GetWorldBounds();

      if ( optionalBbounds == null )
      {
        RJLog.Log( "No Bounds!" );
        ClearFlags();
        return; 
      }

      var bounds = (Aabb) optionalBbounds;

      if (  moveToMinX || moveToMaxX )
      {
        this.SetGlobalX( ( moveToMinX ? bounds.Position : bounds.End ).X );
      }

      if (  moveToMinY || moveToMaxY )
      {
        this.SetGlobalY( ( moveToMinY ? bounds.Position : bounds.End ).Y );
      }

      if (  moveToMinZ || moveToMaxZ )
      {
        this.SetGlobalZ( ( moveToMinZ ? bounds.Position : bounds.End ).Z );
      }

      ClearFlags();
      

    }

    void ClearFlags()
    {
      moveToMinX = false;      
      moveToMaxX = false;

      moveToMinY = false;
      moveToMaxY = false;

      moveToMinZ = false;
      moveToMaxZ = false;
    }

#endif
    public static readonly Quaternion YawFlipRotation = Quaternion.FromEuler( new Vector3( 0, 180, 0 ) / 180 * Mathf.Pi );

    public static void Connect( Node3D target, Node3D targetPin, Node3D sourcePin )
    {
      var targetRotation    = target.GlobalQuaternion();
      var targetPinRotation = targetPin.GlobalQuaternion();

      var pinToParent = targetPinRotation.GetDifference( targetRotation );
      
      var forward = sourcePin.GlobalForward();
      var up      = sourcePin.GlobalUp();

      var rotation = ConnectionPin.YawFlipRotation * pinToParent;

      target.LookTowards( forward, up, rotation );

      var offset = ( sourcePin.GlobalPosition - targetPin.GlobalPosition );
      target.GlobalTranslate( offset );
    } 
  }
}