// Author: Hector Navarro (hnavarro@ciens.ucv.ve)
//         Juan Carlos De Abreu (jcabreur@gmail.com)
//
// This file define an Axis Aligned Bounding Box class that can be used to
// detect collision.
//
// An use of this class can be;
// AABB aabb(Vec3f(0, 0, 0), Vec3f(1, 1, 1));
// return aabb.IsInside(Vec3f(0.5, 0.5, 0.5));

#ifndef AABB_H__
#define AABB_H__

#include "../global.h"
#include "../Math/Vector.h"
#include "../Base/Memory/MMObject.h"
#include "../Base/Memory/SmartPointer.h"

BEGIN_TEG_NAMESPACE();

class Face;
class Group;

class AABB {
 public:	
  // AABB constructors and destructor.
  AABB();
  AABB(const Vec3f& min_vertex, const Vec3f& max_vetex);
  AABB(const Group& group);
  AABB(const Group& group, const std::vector<int>& faces);
  ~AABB();

  // Accessor and mutator methods to AABB attributes.
  const Vec3f& min_vertex() const;
  const Vec3f& max_vertex() const;
  void set_min_vertex(const Vec3f& min_vertex);
  void set_max_vertex(const Vec3f& max_vertex);

  // Methods to get the size, center of a bounding box and to know if a vertex
  // is inside of a bounding box.
  Vec3f GetSize() const;
  Vec3f GetCenter() const;
  bool IsInside(const Vec3f& vertex) const;
  bool IsInside(const Group& group, const Face& face) const;
  int CountVertex(const Group& group, const Face& face);

  // Method to split by one axi an AABB box in two AABB.
  void Split(int axis, AABB& left, AABB& right, float t) const;

  // Methods to save and load to a file the AABB.
  void Load(FILE* f);
  void Save(FILE* f) const;
  
  // Method to display the bounding box.
  void Render() const;
  AUTO_SIZE();

 private:
  // AABB attributes.
  Vec3f min_vertex_, max_vertex_;
};

END_TEG_NAMESPACE();

#endif  // AABB_H__
