//
//  Rect.h
//  Meteor
//
//  Created by Cesar Parent on 13/07/2015.
//  Copyright (c) 2015 Cesar Parent. All rights reserved.
//

#ifndef __Meteor__Rect__
#define __Meteor__Rect__

#include <cstdio>
#include "Vec.h"

NS_BEGIN

/*!
 * @class           Rect
 * @ingroup         Geometry
 * @brief           An object that represents an axis-aligned rectangle.
 */
class Rect
{
public:
    /*!
     * @brief       The NULL rectangle is used to signal the absence of one (no intersection).
     */
    static const Rect   nullRect;
    
    /*!
     * @brief       Rectangle defined by <code>{0, 0, 0, 0}</code>.
     */
    static const Rect   zeroRect;
    
    /*!
     * @brief       X coordinate of the top-left corner of <code>this</code>.
     */
    float           x;
    
    /*!
     * @brief       Y coordinate of the top-left corner of <code>this</code>.
     */
    float           y;
    
    /*!
     * @brief       Width of <code>this</code>.
     */
    float           w;
    
    /*!
     * @brief       Height of <code>this</code>.
     */
    float           h;
    
    /**
     * @name        Creating Rectangles
     * @{
     */
    
    /*!
     * @brief       Creates a new rectangle.
     * @param       x       X coordinate of the rectangle's top left corner. Defaults to 0.
     * @param       y       Y coordinate of the rectangle's top left corner. Defaults to 0.
     * @param       w       The rectangle's width. Defaults to 0.
     * @param       h       The rectangle's height. Defaults to 0.
     */
    Rect(float x = 0, float y = 0, float w = 0, float h = 0);
    
    /*!
     * @brief       Returns a rectangle that is smaller or larger than the source rectangle,
     *              with the same center point.
     * @param       dx      The offset value for the x-coordinate.
     * @param       dy      The offset value for the y-coordinate.
     * @return      A rectangle. The origin value is offset in the x-axis by the distance specified
     *              by the dx parameter and in the y-axis by the distance specified by the dy
     *              parameter, and its size adjusted by (2*dx,2*dy), relative to the source
     *              rectangle. If dx and dy are positive values, then the rectangle’s size is
     *              decreased. If dx and dy are negative values, the rectangle’s size is increased.
     */
    Rect inset(float dx, float dy) const;
    
    /*!
     * @brief       Returns a rectangle with an origin that is offset from that of the source
     *              rectangle.
     * @param       dx      The offset value for the x-coordinate.
     * @param       dy      The offset value for the y-coordinate.
     * @return      A rectangle that is the same size as the source, but with its origin offset by
     *              dx units along the x-axis and dy units along the y-axis with respect to the
     *              source. Returns a null rectangle if rect is a null rectangle.
     */
    Rect offset(float dx, float dy) const;
    
    /*!
     * @brief       Returnsa a rectangle obtained by intersecting the rectangle with another
     *              rectangle.
     * @details     If no intersection is found, <code>Rect::nullRect</code> is returned.
     * @param       rect    Rectangle to check for interesction with.
     * @return      Intersection rectangle, or <code>Rect::nullRect</code> if there isn't one.
     */
    Rect
    intersectionWithRect(Rect rect) const;
    
    /**
     * @}
     */
    
    /*!
     * @internal
     * @brief       Rectangle copy constructor.
     * @param       rhs     Rectanle to copy.
     */
    Rect(const Rect& rhs);
    
    /*!
     * @internal
     * @brief       Assignement operator
     * @param       rhs     Rect to which <code>this</code> is assigned
     */
    Rect&
    operator=(const Rect& rhs);
    
    /**
     * @name        Inspecting a Rectangle's physical properties.
     * @{
     */
    
    /*!
     * @brief       Returns the rectangle's right edge position.
     * @return      The rectangle's right edge position
     */
    float
    maxX() const;
    
    /*!
     * @brief       Returns the rectangle's bottom edge position.
     * @return      The rectangle's bottom edge position
     */
    float
    maxY() const;
    
    /*!
     * @brief       Returns the rectangle's left edge position.
     * @return      The rectangle's left edge position
     */
    float
    minX() const;
    
    /*!
     * @brief       Returns the rectangle's top edge position.
     * @return      The rectangle's top edge position
     */
    float
    minY() const;
    
    
    /*!
     * @brief       Returns the rectangle's center.
     * @return      The rectangle's center.
     */
    vec2 center() const;
    
    /**
     * @}
     */
    
    /*!
     * @internal
     * @brief       Equality comparison operator.
     */
    bool
    operator==(Rect rect) const;
    
    /*!
     * @internal
     * @brief       Inequality comparison operator.
     */
    bool
    operator!=(Rect rect) const;
    
private:
    
    /*!
     * @brief       Check wether <code>this</code> is the Null rectangle.
     * @return      True if <code>this</code> is <code>Rect::nullRect</code>, false otherwise.
     */
    bool isNullRect() const;
};

NS_END

#endif /* defined(__Meteor__Rect__) */
