#include "Vector4.hpp"
#include "Vector3.hpp"
#include "Vector2.hpp"
#include "Color.hpp"
#include "Quaternion.hpp"
#include <cmath>

const TSE::Vector4 TSE::Vector4::one = TSE::Vector4(1,1,1,1);
const TSE::Vector4 TSE::Vector4::zero = TSE::Vector4(0,0,0,0);

TSE::Vector4::Vector4() { }

TSE::Vector4::Vector4(float _x, float _y, float _z, float _w)
{
    x = _x;
    y = _y;
    z = _z;
    w = _w;
}

TSE::Vector4::Vector4(const Vector4 &other)
{
    x = other.x;
    y = other.y;
    z = other.z;
    w = other.w;
}

TSE::Vector4::Vector4(const Vector2 &other)
{
    x = other.x;
    y = other.y;
}

TSE::Vector4::Vector4(const Vector3 &other)
{
    x = other.x;
    y = other.y;
    z = other.z;
}

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

TSE::Vector4::Vector4(const Quaternion &other)
{
    x = other.x;
    y = other.y;
    z = other.z;
    w = other.w;
}

bool TSE::Vector4::IsValid() const
{
    return !std::isnan(x) && !std::isnan(y) && !std::isnan(z) && !std::isnan(w);
}

TSE::string TSE::Vector4::ToString() const
{
    return "(" + std::to_string(x) + "|" + std::to_string(y) + "|" + std::to_string(z) + "|" + std::to_string(w) + ")";
}

TSE::Vector2 TSE::Vector4::ToVector2() const
{
    return Vector2(x,y);
}

TSE::Vector3 TSE::Vector4::ToVector3() const
{
    return Vector3(x,y,z);
}

TSE::Color TSE::Vector4::ToColor() const
{
    return Color(x,y,z,w);
}

TSE::Quaternion TSE::Vector4::ToQuaternion() const
{
    return Quaternion(x,y,z,w);
}

TSE::Vector4 TSE::Vector4::operator+(const Vector4 &other) const
{
    return Vector4(x + other.x, y + other.y, z + other.z, w + other.w);
}

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

TSE::Vector4 TSE::Vector4::operator-(const Vector4 &other) const
{
    return Vector4(x - other.x, y - other.y, z - other.z, w - other.w);
}

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

TSE::Vector4 TSE::Vector4::operator*(const Vector4 &other) const
{
    return Vector4(x * other.x, y * other.y, z * other.z, w * other.w);
}

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

TSE::Vector4 TSE::Vector4::operator/(const Vector4 &other) const
{
    return Vector4(x / other.x, y / other.y, z / other.z, w / other.w);
}

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

TSE::Vector4 TSE::Vector4::operator*(const float other) const
{
    return Vector4(x * other, y * other, z * other, w * other);
}

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

TSE::Vector4 TSE::Vector4::operator/(const float other) const
{
    return Vector4(x / other, y / other, z / other, w / other);
}

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

bool TSE::Vector4::operator==(const Vector4 &other) const
{
    return x == other.x && y == other.y && z == other.z && w == other.w;
}

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