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



namespace Rokojori
{
  [Tool]
  [GlobalClass]
  public partial class ConnectionPinTester:Node3D
  {
    [Export]
    public ConnectionPin fromPin;

    [Export]
    public Node3D toParent;
    [Export]
    public ConnectionPin toPin;

    [Export]
    public bool update = false;

    [Export]
    public bool updateAlways = false;

    [Export]
    public Vector3 eulerRotation;

    [Export]
    public bool diff_reverse = false;

    [Export]
    public bool mult_reverse = false;

    [Export]
    public Vector4 targetPin;

    [Export]
    public Vector4 currentPin;

    [Export]
    public Vector4 needed;

    [Export]
    public Vector4 oldApplying;

    [Export]
    public Vector4 applyingTargetApplied;

    
    [Export]
    public Vector4 pinApplyied;

    [Export]
    public Node3D applyingTarget;

    [Export]
    public Node3D forwardTarget;

    [Export]
    public Vector3 customRotationEulers;

    [Export]
    public bool rotateBefore;

    public override void _Process( double delta )
    {
      Connect3();
    }

    void Connect3()
    {      
      if ( ! ( update || updateAlways ) )
      {
        return;
      }

      update = false;

      ConnectionPin.Connect( toParent, toPin, fromPin );
    }

    void Connect2()
    {
      if ( ! ( update || updateAlways ) )
      {
        return;
      }

      update = false;


      var targetRotation     = fromPin.GetGlobalQuaternion();      
      var currentPinRotation = toPin.GetGlobalQuaternion();
      var parentRotation     = applyingTarget.GetGlobalQuaternion();


      var pinToParent =  diff_reverse ? 
                         Math3D.GetQuaternionDifference( currentPinRotation, parentRotation ) :
                         Math3D.GetQuaternionDifference( parentRotation, currentPinRotation );


      
      var forward = fromPin.GlobalForward();
      var up      = fromPin.GlobalUp();

      var customRotation = Quaternion.FromEuler( customRotationEulers / 180 * Mathf.Pi ) * pinToParent;

      forwardTarget.GlobalPosition = applyingTarget.GlobalPosition + forward;

      targetPin = targetRotation.AsVector4();
      currentPin = currentPinRotation.AsVector4();
      needed = pinToParent.AsVector4();
      oldApplying = parentRotation.AsVector4();
      applyingTargetApplied = Vector4.One * -1;
      pinApplyied = Vector4.One * -1;

      applyingTarget.LookTowards( forward, up, customRotation );

      var offset = ( fromPin.GlobalPosition - toPin.GlobalPosition );
      applyingTarget.GlobalTranslate( offset );

      

    }

    void Connect()
    {
      if ( ! ( update || updateAlways ) )
      {
        return;
      }

      update = false;

      var eulerRads = eulerRotation / 180 * Mathf.Pi;

      var targetRotation = fromPin.GetGlobalQuaternion();
      
      var currentRotation = toPin.GetGlobalQuaternion();
      


      //toPin.SetGlobalQuaternion( targetRotation );

      var neededRotation =  diff_reverse ? 
                            Math3D.GetQuaternionDifference( currentRotation, targetRotation ) :
                            Math3D.GetQuaternionDifference( targetRotation, currentRotation );

    
      var oldRotation = applyingTarget.GetGlobalQuaternion();

      var resultRotation = mult_reverse ? neededRotation * currentRotation : 
                                           oldRotation * neededRotation;
                                          
      var pinResultRotation = mult_reverse ? neededRotation * currentRotation : 
                                           currentRotation * neededRotation;

      RJLog.Log( 
        "Target:", targetRotation, "\n",
        "Current:", currentRotation, "\n",
        "Needed:", neededRotation, "\n",
        "OldRotation:", oldRotation, "\n",
        "Applied:", resultRotation,"\n",
        "Pin:", pinResultRotation
      );

      targetPin = targetRotation.AsVector4();
      currentPin = currentRotation.AsVector4();
      needed = neededRotation.AsVector4();
      oldApplying = oldRotation.AsVector4();
      applyingTargetApplied = resultRotation.AsVector4();
      pinApplyied = pinResultRotation.AsVector4();

      applyingTarget.SetGlobalQuaternion( resultRotation );
      


      //var positionOffset = fromPin.GlobalPosition - toPin.GlobalPosition;

      //toParent.GlobalPosition += positionOffset;

      //toPin.SetGlobalQuaternion( currentRotation * neededRotation );
      //Math3D.SetGlobalRotation( toPin, targetRotation );
    }



  }
}