#include <stdio.h>
#include <stdbool.h>
#include <GL/glew.h>
#include <math.h>

#include "matrixMath.h"

#define EPSILON 0.001f

void printTest(char* name, bool result) {
	if (result) {
		printf("    PASSED - ");
	} else {
		printf("!!! FAILED - ");
	}
	printf("%s", name);
	printf("\n");
}

void testSumDiff() {
	mat3 A = {1.0f, 0.0f, 0.0f, -1.0f, 0.0f, -1.0f, 1.0f, -1.0f, 9.0f};
	mat3 B = {0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 8.0f};
	GLfloat target = 7.0f;

	GLfloat value = mat3SumDiff(&A, &B);

	bool result = fabs(value - target) < EPSILON;

	if (!result) {
		printf("\nA:\n");
		mat3Print(&A);
		printf("\nB:\n");
		mat3Print(&B);
		printf("target: %f\n", target);
		printf("value: %f\n", value);
	}

	printTest("mat3SumDiff", result);
}

void testMat3Adjoint() {
	mat3 M = {2.0f, 0.0f, 1.0f, -1.0f, 5.0f, -1.0f, 3.0f, 2.0f, -2.0f};
	mat3 target = {-8.0f, 5.0f, -17.0f, -2.0f, -7.0f, 4.0f, -5.0f, -1.0f, 10.0f};

	mat3Adjoint(&M, &M);

	printTest("mat3Adjoint", mat3SumDiff(&M, &target) < EPSILON);
}

void testMat3MultiplyScalar() {
	mat3 M = {1.0f, 2.0f, 3.0f, 4.0f, 0.0f, -1.5f, -2.5f, -3.5f, -4.5f};
	GLfloat x = 0.9f;
	mat3 target = {0.9f, 1.8f, 2.7f, 3.6f, 0.0f, -1.35f, -2.25f, -3.15f, -4.05f};

	mat3MultiplyScalar(&M, &M, x);

	printTest("mat3MultiplyScalar", mat3SumDiff(&M, &target) < EPSILON);
}

void testMat3Determinant() {
	mat3 M = {1.0f, -3.0f, 2.0f, 3.0f, -1.0f, 3.0f, 2.0f, -3.0f, 1.0f};
	GLfloat target = -15.0f;

	printTest("mat3Determinant", fabs(mat3Determinant(&M) - target) < EPSILON);
}

void testMat3Inverse() {
	mat3 M = {1.0f, 2.0f, -1.0f, 2.0f, 1.0f, 2.0f, -1.0f, 2.0f, 1.0f};
	mat3 target = {0.1875f, 0.25f, -0.3125f, 0.2f, 0.0f, 0.25f, -0.3125f, 0.25f, 0.1875f};

	mat3Inverse(&M, &M);

	printTest("mat3Inverse", mat3SumDiff(&M, &target) < EPSILON);
}

int main(void) {
	testSumDiff();
	testMat3Adjoint();
	testMat3MultiplyScalar();
	testMat3Determinant();
	testMat3Inverse();
}