#include "SharedTools.h"

int SharedTools::BoundsCheck(int min, int max, int value)
{
	int result = value;
	if (value < min)
	{
		result = min;
	}
	else if (value > max)
	{
		result = max;
	}
	return result;
}

float SharedTools::BoundsCheck(float min, float max, float value)
{
	float result = value;
	if (value < min)
	{
		result = min;
	}
	else if (value > max)
	{
		result = max;
	}
	return result;
}

Matrix SharedTools::GetTranslateMatrix(const float x, const float y, const float z)
{
	return Matrix({ 1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1 });
}

Matrix SharedTools::GetTranslateMatrix(const Vertex& position)
{
	return GetTranslateMatrix(position.GetX(), position.GetY(), position.GetZ());
}

Matrix SharedTools::GetScaleMatrix(const float x, const float y, const float z)
{
	return Matrix({ x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1 });
}

Matrix SharedTools::GetRotationMatrix(const Axis rotAxis, const float rotDegrees)
{
	float rotationRadian = DegreesToRadians(rotDegrees);
	switch (rotAxis)
	{
	case (Axis::X):
		return Matrix({ 1, 0, 0, 0, 0, cos(rotationRadian), -sin(rotationRadian), 0, 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1 });
	case (Axis::Y):
		return Matrix({ cos(rotationRadian), 0, sin(rotationRadian), 0, 0, 1, 0, 0, -sin(rotationRadian), 0, cos(rotationRadian), 0, 0, 0, 0, 1 });
	case (Axis::Z):
		return Matrix({ cos(rotationRadian), -sin(rotationRadian), 0, 0, sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 });
	default:
		throw "Invalid axis selected";
	}
}

Matrix SharedTools::GetRotationMatrixFromPoint(const Axis rotAxis, const float rotDegrees, const float x, const float y, const float z)
{
	return GetTranslateMatrix(x, y, z) * GetRotationMatrix(rotAxis, rotDegrees) * GetTranslateMatrix(-x, -y, -z);
}

float SharedTools::DegreesToRadians(const float degrees)
{
	return (degrees * PI) / 180;
}       

Matrix SharedTools::GetOrthegraphicProjectionMatrix(float d)
{
	return Matrix({ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, d, 0, 0, 0, 1 });
}

Matrix SharedTools::GetPerspectiveProjectionMatrix(float d, float aspectRatio)
{
	float distanceAspect = d / aspectRatio;

	return Matrix({ distanceAspect, 0, 0, 0, 0, d, 0, 0, 0, 0, d, 0, 0, 0, 1, 0 });
}

Matrix SharedTools::GetViewMatrix(float d, int width, int height)
{
	float widthCenter = (float) width / 2.0f;
	float heightCenter = (float) height / 2.0f;
	float distanceCenter = (float) d / 2.0f;

	return Matrix({ widthCenter, 0, 0, widthCenter, 0, -heightCenter, 0, heightCenter, 0, 0, distanceCenter, distanceCenter, 0, 0, 0, 1 });
}

Matrix SharedTools::GetCameraTranslateMatrix(const float x, const float y, const float z)
{
	return GetTranslateMatrix(-x, -y, -z);	
}

Matrix SharedTools::GetCameraTranslateMatrix(const Vertex& position)
{
	return GetTranslateMatrix(-position.GetX(), -position.GetY(), -position.GetZ());
}


Matrix SharedTools::GetCameraRotationMatrix(const Axis rotAxis, const float rotDegrees)
{
	float rotationRadian = DegreesToRadians(rotDegrees);
	switch (rotAxis)
	{
	case (Axis::X):
		return Matrix({ 1, 0, 0, 0, 0, cos(rotationRadian), sin(rotationRadian), 0, 0, -sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1 });
	case (Axis::Y):
		return Matrix({ cos(rotationRadian), 0, -sin(rotationRadian), 0, 0, 1, 0, 0, sin(rotationRadian), 0, cos(rotationRadian), 0, 0, 0, 0, 1 });
	case (Axis::Z):
		return Matrix({ cos(rotationRadian), sin(rotationRadian), 0, 0, -sin(rotationRadian), cos(rotationRadian), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 });
	default:
		throw "Invalid axis selected";
	}
}
