#if GTEST
#include <gtest/gtest.h>
#include <math.h>
#include <limits>

#include "Quaternion.h"

#define FLOAT_INFINITY std::numeric_limits<float>::infinity()

TEST(Quaternion, Normalize) {
	bool r = false;

	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Quaternion q = Quaternion::identity;

	q = q1;
	q.Normalize();
	r = q == q1;
	EXPECT_TRUE(r) << "q.Normalzed 0 0 0 1";

	q = Quaternion::Normalize(q1);
	r = q == q1;
	EXPECT_TRUE(r) << "Quaternion::Normalize 0 0 0 1";
}

TEST(Quaternion, ToAngles) {
	bool r = false;

	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Vector3 v = Vector3::zero;

	v = Quaternion::ToAngles(q1);
	r = v == Vector3(0, 0, 0);
	EXPECT_TRUE(r) << "Quaternion::ToAngles 0 0 0 1";

	q1 = Quaternion(1, 0, 0, 0);
	v = Quaternion::ToAngles(q1);
	r = v == Vector3(180, 0, 0);
	EXPECT_TRUE(r) << "Quaternion::ToAngles 1 0 0 0";
}

TEST(Quaternion, Multiplication) {
	bool r = false;

	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Quaternion q2 = Quaternion(1, 0, 0, 0);
	Quaternion q = Quaternion::identity;

	q = q1 * q2;
	r = q == Quaternion(1, 0, 0, 0);
	EXPECT_TRUE(r) << "0 0 0 1 * 1 0 0 0";
}

TEST(Quaternion, MultiplicationVector) {
	bool r = false;

	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Vector3 v1 = Vector3(0, 1, 0);
	Vector3 v = Vector3::zero;

	v = q1 * v1;
	r = v == Vector3(0, 1, 0);
	EXPECT_TRUE(r) << "0 0 0 1 * Vector 0 1 0";

	q1 = Quaternion(1, 0, 0, 0);
	v = q1 * v1;
	r = v == Vector3(0, -1, 0);
	EXPECT_TRUE(r) << "1 0 0 0 * Vector 0 1 0";
}

TEST(Quaternion, Equality) {
	bool r = false;

	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Quaternion q2 = Quaternion(1, 0, 0, 0);

	r = q1 == q2;
	EXPECT_FALSE(r) << " 0 0 0 1 == 1 0 0 0";

	q2 = Quaternion(0, 0, 0, 1);
	r = q1 == q2;
	EXPECT_TRUE(r) << "0 0 0 1 == 0 0 0 1";
}

TEST(Quaternion, Inverse) {

}

TEST(Quaternion, LookRotation) {

}

TEST(Quaternion, FromToRotation) {

}

TEST(Quaternion, RotateTowards) {

}

TEST(Quaternion, AngleAxis) {

}

TEST(Quaternion, Angle) {

}

TEST(Quaternion, Slerp) {

}

TEST(Quaternion, SlerpUnclamped) {

}

TEST(Quaternion, Euler) {
	bool r = false;

	Vector3 v1 = Vector3(0, 0, 0);
	Quaternion q = Quaternion::identity;

	q = Quaternion::Euler(v1);
	r = q == Quaternion::identity;
	EXPECT_TRUE(r) << "Euler Vector 0 0 0";

	q = Quaternion::Euler(0, 0, 0);
	r = q == Quaternion::identity;
	EXPECT_TRUE(r) << "Euler 0 0 0";

	v1 = Vector3(90, 90, -90);
	q = Quaternion::Euler(v1);
	r = q == Quaternion(0, 0.707106709F, -0.707106709F, 0);
	EXPECT_TRUE(r) << "Euler Vector 90 90 -90";

	q = Quaternion::Euler(90, 90, -90);
	r = q == Quaternion(0, 0.707106709F, -0.707106709F, 0);
	EXPECT_TRUE(r) << "Euler 90 90 -90";
}

TEST(Quaternion, GetAngleAround) {
	bool r = false;

	Vector3 v1 = Vector3(0, 1, 0);
	Quaternion q1 = Quaternion(0, 0, 0, 1);
	float f;

	f = Quaternion::GetAngleAround(v1, q1);
	EXPECT_FLOAT_EQ(f, 0) << "GetAngleAround 0 1 0 , 0 0 0 1";

	q1 = Quaternion(0, 0.707106709F, -0.707106709F, 0);
	f = Quaternion::GetAngleAround(v1, q1);
	EXPECT_FLOAT_EQ(f, 180) << "GetAngleAround 0 1 0 , 0 0.7 -0.7 0";

	v1 = Vector3(0, 0, 0);
	f = Quaternion::GetAngleAround(v1, q1);
	r = isnan(f);
	EXPECT_TRUE(r) << "GetAngleAround 0 0 0 , 0 0.7 -0.7 0";
}

TEST(Quaternion, GetRotationAround) {
	bool r = false;

	Vector3 v1 = Vector3(0, 1, 0);
	Quaternion q1 = Quaternion(0, 0, 0, 1);
	Quaternion q = Quaternion::identity;

	q = Quaternion::GetRotationAround(v1, q1);
	r = q == Quaternion::identity;
	EXPECT_TRUE(r) << "GetRotationAround 0 1 0 , 0 0 0 1";

	q1 = Quaternion(0, 0.707106709F, -0.707106709F, 0);
	q = Quaternion::GetRotationAround(v1, q1);
	r = q == Quaternion(0, 1, 0, 0);
	EXPECT_TRUE(r) << "GetRotationAround 0 1 0 , 0 0.7 -0.7 0";

	v1 = Vector3(0, 0, 0);
	q = Quaternion::GetRotationAround(v1, q1);
	r = isnan(q.x) && isnan(q.y) && isnan(q.z) && isnan(q.w);
	EXPECT_TRUE(r) << "GetRotationAround 0 0 0 , 0 0.7 -0.7 0";
}

TEST(Quaternion, GetSwingTwist) {

}

TEST(Quaternion, Dot) {
}
#endif