//
// .SUMMARY:
// Defines the Box class.
//
// .DESCRIPTION
// The Box class is used to store retangular entities like windows, viewports,
// clipping and extend rectangles, among others.
//
// .SEE ALSO
// Point
//
//

#ifndef Box_H
#define Box_H

#include <gdefines.h>

#ifndef Point_H
#include <Point.hpp>
#endif

class SProjection;

class Box
{
    Point _bll, _bur;
    //		Lower-left and upper-right coordinates that defines the rectangle.

public:
    Box() {}
    //		Empty constructor.

    Box(const Point& o, const Point& c);
    //		Normal constructor.
    //		Input :
    //			o : point (lower-left)
    //			c : point (upper-right)

    ~Box() {}
    //		Normal destructor.

    Box(const Box&);
    //		Copy initializer.

    short contains(const Point& p) const;
    //		Check if Box contains Point p.
    //		Input :
    //			p : point
    //		Return :
    //			TRUE  : box contains point p
    //			FALSE : box not contains point p

    short contains(const Box& b) const;
    //		Check if Box contains Box b.
    //		Input :
    //			b : box
    //		Return :
    //			TRUE  : box contains b
    //			FALSE : box not contains b

    short intersects(const Box& b) const;
    //		Check if Box intersects Box b.
    //		Input :
    //			b : box
    //		Return :
    //			TRUE  : box intersects b
    //			FALSE : box not intersects b

    Box intersection(const Box& b) const;
    //		Perform the intersection between Box and Box b. Return the new box.

    Box unionx(const Box& b) const;
    //		Perform the union between Box and Box b. Return the new box.

    Point& lowerLeft() { return _bll; }
    //		Return the lower-left corner of the rectangle.

    Point& upperRight() { return _bur; }
    //		Return the upper-right corner of the rectangle.

    void lowerLeft(const Point& pp) { _bll = pp; }
    //		Initialize the lower-left corner of the rectangle.
    //		Input :
    //			pp : point

    void upperRight(const Point& pp) { _bur = pp; }
    //		Initialize the upper-right corner of the rectangle.
    //		Input :
    //			pp : point

    float upperRightX() const { return _bur.x(); }
    //		Return the X coordinate from the upper-right corner of the rectangle.

    float upperRightY() const { return _bur.y(); }
    //		Return the Y coordinate from the upper-right corner of the rectangle.

    float lowerLeftX() const { return _bll.x(); }
    //		Return the X coordinate from the lower-left corner of the rectangle.

    float lowerLeftY() const { return _bll.y(); }
    //		Return the Y coordinate from the lower-left corner of the rectangle.

    void upperRightX(float f) { _bur.x(f); }
    //		Set the X coordinate from the upper-right corner of the rectangle.
    //		Input :
    //			f : float variable

    void upperRightY(float f) { _bur.y(f); }
    //		Set the Y coordinate from the upper-right corner of the rectangle.
    //		Input :
    //			f : float variable

    void lowerLeftX(float f) { _bll.x(f); }
    //		Set the X coordinate from the lower-left corner of the rectangle.
    //		Input :
    //			f : float variable

    void lowerLeftY(float f) { _bll.y(f); }
    //		Set the Y coordinate from the lower-left corner of the rectangle.
    //		Input :
    //			f : float variable


    void print();
    //		Print box coordinates on the console.

    void init(Point& l, Point& r)
    {
        _bll = l;
        _bur = r;
    }
    //		Store the first (or a new) rectangle.
    //		Input:
    //			l : lower-left corner coordinate
    //			r : upper-right corner coordinate

    float width() { return mv_abs(_bur.x() - _bll.x()); }
    //		Return the width of the rectangle.

    float height() { return mv_abs(_bur.y() - _bll.y()); }
    //		Return the height of the rectangle.

    Box operator=(Box& b);
    //		Assignment capability for class Box instances.

    void remap(SProjection* in, SProjection* out);
    //		Remap box in projection "in" to box in projection "out".
    //		Input :
    //			in  : input projection
    //			out : output projection

    void remap(SProjection* out);
    //		Remap box defined in latitude and longitude to
    //		projection "out". This method does not just remap the
    //		two points that define the box. It searches for
    //		the minimum and maximum projection coordinates
    //		values along the edges of the box.
    //		Input :
    //			out : desired projection

    short load(FILE* fp);
    short save(FILE* fp);
};

#endif
