#ifndef BOX_HPP_INCLUDED
#define BOX_HPP_INCLUDED

#include <iostream>
#include <cstdint>
#include "Point.hpp"

class Point;

class Box
{
    public:
        Box();
        /*!
         * @param X Top-left x-axis coordinate of the box to construct
         * @param Y Top-left y-axis coordinate of the box to construct
         * @param Width The width of the box to construct
         * @param Height The Height of the box to construct
         */
        Box(std::int32_t X, std::int32_t Y, std::int32_t Width, std::int32_t Height);
        Box(const Box& B);

        std::int32_t X; //!< The top-left x-axis coordinate
        std::int32_t Y; //!< The top-left y-axis coordinate
        std::int32_t Width;
        std::int32_t Height;

        bool Contains(const Point& P) const;
        bool Contains(const Box& B) const;
        bool Contains(std::int32_t X, std::int32_t Y) const;

        Point GetMiddle() const;
        std::int32_t GetX2() const;
        std::int32_t GetY2() const;

        bool OnScreen() const; //!< @returns True if the box is within the client canvas bounds
        bool IsValid() const; //!< @returns True if the x and y axis coordinates, width and height are greater than or equal to zero

        Point GetUniformRandomPoint() const;
        Point GetBinomialRandomPoint(double ProbabilityX, double ProbabilityY) const;
        Point GetNormalRandomPoint(double PercentageDeviationX, double PercentageDeviationY) const;

        Point GetHybridRandomPoint(double ProbabilityX, double ProbabilityY, double StandardDeviationX, double StandardDeviationY, double PointGenAccuracy) const;
        Point GetProfileHybridRandomPoint() const;
        Point GetProfileHybridRandomPoint(double PointGenAccuracy) const;

        bool operator==(const Box& B) const;
        bool operator!=(const Box& B) const;

        friend std::ostream& operator<<(std::ostream& OS, const Box& B);
        operator bool() const; //!< @returns True if the x and y axis coordinates, width and height are greater than or equal to zero

        ~Box();
};

#endif // BOX_HPP_INCLUDED
