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

namespace Rokojori
{
  public class Box3
	{
    public Vector3 min = Vector3.Zero;
    public Vector3 max = Vector3.Zero;

    public Vector3 center => ( max + min ) / 2f;

    public static implicit operator Box3( Aabb aabb )
    {  
      return Box3.Create( aabb.Position, aabb.End );
    }

    public static implicit operator Aabb( Box3 box )
    {  
      return new Aabb( box.min, box.size ); 
    }

    public void Translate( Vector3 translation )
    {
      min += translation;
      max += translation;
    }

    public static Box3 FromPositionAndScale( Vector3 position, Vector3 scale )
    {
      var max = scale * 0.5f;
      var min = -max;

      return Box3.Create( min + position, max + position );
    } 

    public static Box3 Create( Vector3 min, Vector3 max )
    {
      var b = new Box3();
      b.min = min;
      b.max = max;

      return b;
    }

    public Vector3 size => max - min;

    public void IncludePoint( Vector3 p )
    {
      min = min.Min( p );
      max = max.Max( p );
    }

    public Box2 AsXZBox2()
    {
      var b = new Box2();
      b.min = Math2D.XZ( min );
      b.max = Math2D.XZ( max );

      return b;
    }

    public Vector3 Constrain( Vector3 point )
    {
      point = min.Max( point );
      point = max.Min( point );

      return point;
    }

    public void EnsureYBounds( float minY, float maxY )
    {
      min.Y = Mathf.Min( minY, min.Y );
      max.Y = Mathf.Max( maxY, max.Y );
    }

    public float maxDistance => ( max - min ).Length();

    public static Vector3 Constrain( Vector3 point, Vector3 min, Vector3 max )
    {
      point = min.Max( point );
      point = max.Min( point );

      return point;
    }

    public bool ContainsPoint( Vector3 point )
    {
      if ( ! Range.Contains( min.X, max.X, point.X ) )
      {
        return false;
      }

      if ( ! Range.Contains( min.Z, max.Z, point.Z ) )
      {
        return false;
      }

      if ( ! Range.Contains( min.Y, max.Y, point.Y ) )
      {
        return false;
      }

      return true;
    }


    public void EnsureCorrectness()
    {
      if ( max.X < min.X )
      {
        var b = max.X; max.X = min.X; min.X = b;
      }

      if ( max.Y < min.Y )
      {
        var b = max.Y; max.Y = min.Y; min.Y = b;
      }

      if ( max.Z < min.Z )
      {
        var b = max.Z; max.Z = min.Z; min.Z = b;
      }

    }

  }

}