#include "Color.hpp"
#include "Vector4.hpp"
#include <cmath>

TSE::Color const TSE::Color::red = TSE::Color(1.0f,0.0f,0.0f);
TSE::Color const TSE::Color::blue = TSE::Color(0.0f,1.0f,0.0f);
TSE::Color const TSE::Color::green = TSE::Color(0.0f,0.0f,1.0f);
TSE::Color const TSE::Color::white = TSE::Color(1.0f,1.0f,1.0f);
TSE::Color const TSE::Color::black = TSE::Color(0.0f,0.0f,0.0f);
TSE::Color const TSE::Color::gray = TSE::Color(0.5f,0.5f,0.5f);
TSE::Color const TSE::Color::darkGray = TSE::Color(0.2f,0.2f,0.2f);
TSE::Color const TSE::Color::yellow = TSE::Color(1.0f,1.0f,0.0f);
TSE::Color const TSE::Color::orange = TSE::Color(1.0f,0.5f,0.0f);
TSE::Color const TSE::Color::aqua = TSE::Color(0.0f,1.0f,1.0f);

TSE::Color::Color() { }

TSE::Color::Color(float _r, float _g, float _b)
{
    r = _r;
    g = _g;
    b = _b;
}

TSE::Color::Color(float _r, float _g, float _b, float _a)
{
    r = _r;
    g = _g;
    b = _b;
    a = _a;
}

TSE::Color::Color(byte _r, byte _g, byte _b)
{
    r = _r / 255.0f;
    g = _g / 255.0f;
    b = _b / 255.0f;
}

TSE::Color::Color(byte _r, byte _g, byte _b, byte _a)
{
    r = _r / 255.0f;
    g = _g / 255.0f;
    b = _b / 255.0f;
    a = _a / 255.0f;
}

TSE::Color::Color(const Color &other)
{
    r = other.r;
    g = other.g;
    b = other.b;
    a = other.a;
}

TSE::Color::Color(const Vector4 &other)
{
    r = other.x;
    g = other.y;
    b = other.z;
    a = other.w;
}

bool TSE::Color::IsValid() const
{
    return (!std::isnan(r) && r >= 0 && r <= 1) && (!std::isnan(g) && g >= 0 && g <= 1) && (!std::isnan(b) && b >= 0 && b <= 1) && (!std::isnan(a) && a >= 0 && a <= 1);
}

TSE::byte TSE::Color::R() const
{
    return r * 255;
}

TSE::byte TSE::Color::G() const
{
    return g * 255;
}

TSE::byte TSE::Color::B() const
{
    return b * 255;
}

TSE::byte TSE::Color::A() const
{
    return a * 255;
}

TSE::string TSE::Color::ToString() const
{
    return "(" + std::to_string(r) + "|" + std::to_string(g) + "|" + std::to_string(b) + "|" + std::to_string(a) + ")";
}

TSE::Vector4 TSE::Color::ToVector4() const
{
    return Vector4(r,g,b,a);
}

TSE::Color TSE::Color::Lerp(const Color &a, const Color &b, const float t)
{
    return a + (b - a) * t;
}

TSE::Color TSE::Color::operator+(const Color &other) const
{
    return Vector4(r + other.r, g + other.g, b + other.b, a + other.a);
}

TSE::Color TSE::Color::operator+=(const Color &other)
{
    *this = *this + other;
    return *this;
}

TSE::Color TSE::Color::operator-(const Color &other) const
{
    return Vector4(r - other.r, g - other.g, b - other.b, a - other.a);
}

TSE::Color TSE::Color::operator-=(const Color &other)
{
    *this = *this - other;
    return *this;
}

TSE::Color TSE::Color::operator*(const Color &other) const
{
    return Vector4(r * other.r, g * other.g, b * other.b, a * other.a);
}

TSE::Color TSE::Color::operator*=(const Color &other)
{
    *this = *this * other;
    return *this;
}

TSE::Color TSE::Color::operator/(const Color &other) const
{
    return Vector4(r / other.r, g / other.g, b / other.b, a / other.a);
}

TSE::Color TSE::Color::operator/=(const Color &other)
{
    *this = *this / other;
    return *this;
}

TSE::Color TSE::Color::operator*(const float other) const
{
    return Vector4(r * other, g * other, b * other, a * other);
}

TSE::Color TSE::Color::operator*=(const float other)
{
    *this = *this * other;
    return *this;
}

TSE::Color TSE::Color::operator/(const float other) const
{
    return Vector4(r / other, g / other, b / other, a / other);
}

TSE::Color TSE::Color::operator/=(const float other)
{
    *this = *this / other;
    return *this;
}

bool TSE::Color::operator==(const Color &other) const
{
    return r == other.r && g == other.g && b == other.b && a == other.a;
}

bool TSE::Color::operator!=(const Color &other) const
{
    return !(*this == other);
}
