/******************************************************************************
*	File		-	types.h
*	Author		-	Joey Pollack
*	Date		-	2021/08/30 (y/m/d)
*	Mod Date	-	2021/09/02 (y/m/d)
*	Description	-	Defines some generic types for use through out the engine.
******************************************************************************/

#ifndef TYPES_H_
#define TYPES_H_

#include <cstdint>
#include <glm/glm.hpp>
#include <box2d/box2d.h>


namespace lunarium
{
    ////////////////////////////////////////////////////////////
    //				POINT
    ////////////////////////////////////////////////////////////
    template <typename T>
    struct Vec2
    {
        T X;
        T Y;

        bool operator==(const Vec2<T>& rhs) const { return (this->X == rhs.X && this->Y == rhs.Y);  }
        bool operator!=(const Vec2<T>& rhs) const { return !((*this) == rhs); }
    };

    typedef Vec2<int> Vec2i;
    typedef Vec2<unsigned> Vec2u;
    typedef Vec2<float> Vec2f;

    ///////////////////////////////////////////////////////
    //          SIZE
    //////////////////////////////////////////////////////
    template <typename T>
    struct Size
    {
        T Width;
        T Height;

        bool operator==(const Size<T>& rhs) const { return (this->Width == rhs.Width && this->Height == rhs.Height); }
        bool operator!=(const Size<T>& rhs) const { return !((*this) == rhs); }
    };

    typedef Size<int> Sizei;
    typedef Size<unsigned> Sizeu;
    typedef Size<float> Sizef;
    /////////////////////////////////////////////////

    /////////////////////////////////////////////////
    //          COLOR
    /////////////////////////////////////////////////
    struct Color
	{
		union
		{
			float arr[4];

			struct
			{
				float R;
				float G;
				float B;
				float A;
			};
		};

		Color();
		Color(float _r, float _g, float _b, float _a = 1.0f);

        static Color White();
        static Color Black();
        static Color Red();
        static Color Green();
        static Color Blue();
        static Color Transparent();
	};


    /////////////////////////////////////////////////


    /////////////////////////////////////////////////
    //          RECTANGLE
    /////////////////////////////////////////////////
    struct Rectangle
	{
		float X;
		float Y;
		float HalfWidth;
		float HalfHeight;

        float left() const { return X - HalfWidth; }
        float top() const { return Y - HalfHeight; }
		float right() const { return X + HalfWidth; }
		float bottom() const { return Y + HalfHeight; }

        glm::vec2 CenterPoint() const;
        Sizef FullSize() const;

		Rectangle();
        Rectangle(b2AABB& box);
		Rectangle(float x, float y, float half_width, float half_height);

        void Scale(float x, float y);
		float Area() const;
        bool ContainsPoint(glm::vec2 point) const;

        // centers will be filled out with a vector the goes from the other
        // Rectangle's center to the invoking object's center.
        // This could be used for determining the angle of the intersection.
        bool Intersects(const Rectangle& other, glm::vec2& centers) const;

        static Rectangle MakeFromTopLeft(float left, float top, float width, float height);
	};
    /////////////////////////////////////////////////
}

#endif // TYPES_H_