package MapEditor;

import javax.vecmath.*;

public class AxisAlignedBox implements Cloneable
{
	// Data Invariant: m_corners[0].c <= m_corners[1].c for all c <- {x,y,z}
	private Point3d[] m_corners = new Point3d[2];

	private void reestablish_invariant()
	{
		if(m_corners[0].x > m_corners[1].x)
		{
			double t = m_corners[0].x;
			m_corners[0].x = m_corners[1].x;
			m_corners[1].x = t;
		}
		if(m_corners[0].y > m_corners[1].y)
		{
			double t = m_corners[0].y;
			m_corners[0].y = m_corners[1].y;
			m_corners[1].y = t;
		}
		if(m_corners[0].z > m_corners[1].z)
		{
			double t = m_corners[0].z;
			m_corners[0].z = m_corners[1].z;
			m_corners[1].z = t;
		}
	}

	public AxisAlignedBox(Point3d corner0, Point3d corner1)
	{
		m_corners[0] = corner0;
		m_corners[1] = corner1;
		reestablish_invariant();
	}

	public class Projection
	{
		// Data Invariant: m_corners[0].c <= m_corners[1].c for all c <- {x,y}
		public Point2d[] m_corners = new Point2d[2];
	}

	public Point3d centre()
	{
		Point3d c = (Point3d)m_corners[0].clone();
		c.add(m_corners[1]);
		c.scale(0.5);
		return c;
	}

	public Object clone()
	{
		return new AxisAlignedBox((Point3d)m_corners[0].clone(), (Point3d)m_corners[1].clone());
	}

	public boolean completely_contains(AxisAlignedBox other)
	{
		// Is the other box entirely inside this one? The faces can touch...
		if(m_corners[0].x <= other.m_corners[0].x && other.m_corners[1].x <= m_corners[1].x &&
		   m_corners[0].y <= other.m_corners[0].y && other.m_corners[1].y <= m_corners[1].y &&
		   m_corners[0].z <= other.m_corners[0].z && other.m_corners[1].z <= m_corners[1].z)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public Point3d[] get_bounds()
	{
		return m_corners;
	}

	public Projection project_to_2D_using(AxisPair ap)
	{
		Projection p = new Projection();
		for(int i=0; i<2; ++i) p.m_corners[i] = ap.select_components(m_corners[i]);
		return p;
	}

	public void resize(Point2d corner0, Point2d corner1, AxisPair ap)
	{
		ap.set_relevant_components(m_corners[0], corner0);
		ap.set_relevant_components(m_corners[1], corner1);
		reestablish_invariant();
	}

	public void resize(Point3d corner0, Point3d corner1)
	{
		m_corners[0] = corner0;
		m_corners[1] = corner1;
		reestablish_invariant();
	}

	public void translate(Point2d trans, AxisPair ap)
	{
		for(Point3d c: m_corners) ap.add_offset(c, trans);
	}

	public void translate(Point3d trans)
	{
		for(Point3d c: m_corners) c.add(trans);
	}
}
