/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

#include <catch2/catch_all.hpp>
#include <cmath>

#include "Math/RGBA5551.hpp"

using namespace OpenVulkano::Math;

bool almostEqual(float a, float b, float epsilon = 0.001f) { return std::fabs(a - b) < epsilon; }

TEST_CASE("test_rgba5551_default_ctor", "[RGBA5551]")
{
	RGBA5551 color;
	REQUIRE(color.GetR() == 0);
	REQUIRE(color.GetG() == 0);
	REQUIRE(color.GetB() == 0);
	REQUIRE(color.GetA() == 255);
}

TEST_CASE("test_rgba5551_creation", "[RGBA5551]")
{
	RGBA5551 color1(Vector4uc(255, 255, 255, 129));
	REQUIRE(color1.r == 31);
	REQUIRE(color1.g == 31);
	REQUIRE(color1.b == 31);
	REQUIRE(color1.a == 1);

	RGBA5551 color2(Vector4f(1.0f, 1.0f, 1.0f, 1.0f));
	REQUIRE(color2.r == 31);
	REQUIRE(color2.g == 31);
	REQUIRE(color2.b == 31);
	REQUIRE(color2.a == 1);

	RGBA5551 color3(Vector4i(128, 128, 128, 0));
	REQUIRE(color3.r == 15);
	REQUIRE(color3.g == 15);
	REQUIRE(color3.b == 15);
	REQUIRE(color3.a == 0);
}

TEST_CASE("test_rgba5551_conversion_to_vector3", "[RGBA5551]")
{
	RGBA5551 color(Vector4i(255, 0, 0, 1));
	Vector3f vec = color.Get3Normalized<float>();
	REQUIRE(almostEqual(vec.x, 1.0f));
	REQUIRE(almostEqual(vec.y, 0.0f));
	REQUIRE(almostEqual(vec.z, 0.0f));

	Vector3f vec3 { 0.1f, 0.5f, 1.0f };
	RGBA5551 color2(vec3);
	REQUIRE(almostEqual(color2.GetR_Normalized(), 0.096f));
	REQUIRE(almostEqual(color2.GetG_Normalized(), 0.483f));
	REQUIRE(almostEqual(color2.GetB_Normalized(), 1.0f));
	REQUIRE(almostEqual(color2.GetA_Normalized(), 1.0f));
}

TEST_CASE("test_rgba5551_conversion_to_vector4", "[RGBA5551]")
{
	RGBA5551 color(Vector4i(255, 0, 0, 129));
	Vector4f vec = color.Get4Normalized<float>();
	REQUIRE(almostEqual(vec.x, 1.0f));
	REQUIRE(almostEqual(vec.y, 0.0f));
	REQUIRE(almostEqual(vec.z, 0.0f));
	REQUIRE(almostEqual(vec.w, 1.0f));
}

TEST_CASE("test_rgba5551_conversion_from_vector3", "[RGBA5551]")
{
	Vector3f vec(1.0f, 0.5f, 0.25f);
	RGBA5551 color(vec);
	REQUIRE(color.r == 31);
	REQUIRE(color.g == 15);
	REQUIRE(color.b == 7);
	REQUIRE(color.a == 1);
}

TEST_CASE("test_rgba5551_conversion_from_vector4", "[RGBA5551]")
{
	Vector4f vec(0.0f, 1.0f, 0.5f, 0.0f);
	RGBA5551 color(vec);
	REQUIRE(color.r == 0);
	REQUIRE(color.g == 31);
	REQUIRE(color.b == 15);
	REQUIRE(color.a == 0);
}

TEST_CASE("test_rgba5551_cast_to_vector4", "[RGBA5551]")
{
	RGBA5551 color;
	color.r = 31;
	color.g = 15;
	color.b = 7;
	color.a = 1;
	Vector4f casted = (Vector4f)color;
	REQUIRE(almostEqual(casted.r, 1.0));
	REQUIRE(almostEqual(casted.g, 0.483));
	REQUIRE(almostEqual(casted.b, 0.225));
	REQUIRE(almostEqual(casted.a, 1));
}

TEST_CASE("test_rgba5551_getters_setters", "[RGBA5551]")
{
	RGBA5551 color;
	color.SetR_Normalized(0.1f);
	color.SetG_Normalized(0.5f);
	color.SetB_Normalized(1.0f);
	color.SetA_Normalized(0.7f);

	REQUIRE(almostEqual(color.GetR_Normalized(), 0.096f));
	REQUIRE(almostEqual(color.GetG_Normalized(), 0.483f));
	REQUIRE(almostEqual(color.GetB_Normalized(), 1.0f));
	REQUIRE(color.GetA() == 255);

	color = RGBA5551(Vector3<uint8_t> { 255, 127, 63 });
	Vector3<uint8_t> vec3 = color;

	REQUIRE(vec3.r == 255);
	REQUIRE(vec3.g == 123);
	REQUIRE(vec3.b == 57);
}

TEST_CASE("test_rgba5551_comparison", "[RGBA5551]")
{
	RGBA5551 color1(Vector4<uint8_t>{255, 127, 63, 255});
    RGBA5551 color2(Vector4<uint8_t>{255, 127, 63, 255});
    RGBA5551 color3(Vector4<uint8_t>{63, 127, 255, 255});

	REQUIRE(color1 == color2);
	REQUIRE(color1 != color3);

	{
		RGBA5551 color4 = color1;
        REQUIRE(color4 == color1);
	}

	Vector3<uint8_t> vec3 { 255, 127, 63 };
	color1 = vec3;
	REQUIRE(color1.GetR() == 255);
	REQUIRE(color1.GetG() == 123);
	REQUIRE(color1.GetB() == 57);
	REQUIRE(color1.GetA() == 255);

	Vector4<float> vec4 { 0.1f, 0.5f, 1.0f, 0.7f };
	color1 = vec4;
	REQUIRE(almostEqual(color1.GetR_Normalized(), 0.096f));
	REQUIRE(almostEqual(color1.GetG_Normalized(), 0.483f));
	REQUIRE(almostEqual(color1.GetB_Normalized(), 1.0f));
	REQUIRE(color1.GetA() == 255);
}