#pragma once

#include "Types.hpp"

namespace TSE
{
    class Vector4;

    /// @brief the color class for the engine
    class Color
    {
        public:
        #pragma region members
        float r = 0, g = 0, b = 0, a = 1;
        #pragma endregion members

        #pragma region consts
        static const Color red;
        static const Color green;
        static const Color blue;
        static const Color white;
        static const Color black;
        static const Color gray;
        static const Color darkGray;
        static const Color yellow;
        static const Color orange;
        static const Color aqua;
        #pragma endregion consts

        #pragma region ctor
        /// @brief empty constructor. Gives you a black color with a full alpha
        Color();
        /// @brief construct a color with float values ranging from 0 - 1
        /// @param _r red component
        /// @param _g green component
        /// @param _b blue component
        Color(float _r, float _g, float _b);
        /// @brief construct a color with float values ranging from 0 - 1
        /// @param _r red component
        /// @param _g green component
        /// @param _b blue component
        /// @param _a alpha component
        Color(float _r, float _g, float _b, float _a);
        /// @brief construct a color with byte values ranging from 0 - 255
        /// @param _r red component
        /// @param _g green component
        /// @param _b blue component
        Color(byte _r, byte _g, byte _b);
        /// @brief construct a color with byte values ranging from 0 - 255
        /// @param _r red component
        /// @param _g green component
        /// @param _b blue component
        /// @param _a alpha component
        Color(byte _r, byte _g, byte _b, byte _a);
        /// @brief copy constructor. It copies the values from the input color
        /// @param other input color
        Color(const Color& other);
        /// @brief convert constructor. It converts the values from the input vector4, where x -> r, y -> g, z -> b, w -> a
        /// @param other input vector4
        Color(const Vector4& other);
        #pragma endregion ctor

        #pragma region methods
        /// @brief checks if the individual color chanels have valid values
        /// @return are the values valid
        bool IsValid() const;
        /// @brief gives you the red component as a byte
        /// @return the red component
        byte R() const;
        /// @brief gives you the green component as a byte
        /// @return the green component
        byte G() const;
        /// @brief gives you the blue component as a byte
        /// @return the blue component
        byte B() const;
        /// @brief gives you the alpha component as a byte
        /// @return the alpha component
        byte A() const;
        /// @brief gives you the color as a string representation. mostly for debugging
        /// @return the color in a format like (r|g|b|a)
        string ToString() const;
        /// @brief creates a Vector4 with the same values as the color, where x -> r, y -> g, z -> b, w -> a
        /// @return the color as a Vector4
        Vector4 ToVector4() const;

        #pragma region static
        /// @brief Linearlie interpolates between two colors using t
        /// @param a Color1
        /// @param b Color2
        /// @param t the value that defines how much it schould be Color1 (0) or Color2 (1)
        /// @return the lerped color
        static Color Lerp(const Color& a, const Color& b, const float t);
        #pragma endregion static

        #pragma region operators
        Color operator+(const Color& other) const;
        Color operator+=(const Color& other);
        Color operator-(const Color& other) const;
        Color operator-=(const Color& other);
        Color operator*(const Color& other) const;
        Color operator*=(const Color& other);
        Color operator/(const Color& other) const;
        Color operator/=(const Color& other);
        Color operator*(const float other) const;
        Color operator*=(const float other);
        Color operator/(const float other) const;
        Color operator/=(const float other);
        bool operator==(const Color& other) const;
        bool operator!=(const Color& other) const;
        #pragma endregion operators
        #pragma endregion methods
    };
} // namespace TSE
