/*
 * Easings.c
 *
 * Created: Sun Jun 22 2025 15:52:12
 *  Author Chris
 */
#include "Easings.h"


// ============================================================================================
// Defines


// ============================================================================================
// Variables


// ============================================================================================
// Function Declarations


/*******************************************************************
	Functions
*******************************************************************/
float Linear(float x)
{
	if(x <= 1.0f) {
		return x;
	}

	return 1.0f;
}

float Ease_In_Sine(float x)
{
	if(x <= 1.0f) {
		return (float)( 1 - cosf((x * M_PI) / 2.0f));
	}

	return 1.0f;
}

float Ease_Out_Sine(float x)
{
	if(x <= 1.0f) {
		return (float)(sinf((x * M_PI) / 2.0f));
	}

	return 1.0f;
}

float Ease_InOut_Sine(float x)
{
	if(x <= 1.0f) {
		return (float)(-(cosf(M_PI * x) - 1.0) / 2.0);
	}

	return 1.0f;
}

float Ease_In_Quad(float x)
{
	if(x <= 1.0f) {
		return x * x;
	}

	return 1.0f;
}

float Ease_Out_Quad(float x)
{
	if(x <= 1.0f) {
		return 1 - (1 - x) * (1 - x);
	}

	return 1.0f;
}

float Ease_InOut_Quad(float x)
{
	if(x <= 1.0f) {
		return (float)(x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2);
	}

	return 1.0f;
}

float Ease_In_Cubic(float x)
{
	if(x <= 1.0f) {
		return x * x * x;
	}

	return 1.0f;
}

float Ease_Out_Cubic(float x)
{
	if(x <= 1.0f) {
		return (float)(1 - pow(1 - x, 3));
	}

	return 1.0f;
}

float Ease_InOut_Cubic(float x)
{
	if(x <= 1.0f) {
		return (float)(x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2);
	}

	return 1.0f;
}


float Ease_In_Quart(float x)
{
	if(x <= 1.0f) {
		return x * x * x * x;
	}

	return 1.0f;
}

float Ease_Out_Quart(float x)
{
	if(x <= 1.0f) {
		return (float)(1 - pow(1 - x, 4));
	}

	return 1.0f;
}

float Ease_InOut_Quart(float x)
{
	if(x <= 1.0f) {
		return (float)(x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2);
	}

	return 1.0f;
}


float Ease_In_Quint(float x)
{
	if(x <= 1.0f) {
		return x * x * x * x * x;
	}

	return 1.0f;
}

float Ease_Out_Quint(float x)
{
	if(x <= 1.0f) {
		return (float)(1 - pow(1 - x, 5));
	}

	return 1.0f;
}

float Ease_InOut_Quint(float x)
{
	if(x <= 1.0f) {
		return (float)(x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2);
	}

	return 1.0f;
}


float Ease_In_Expo(float x)
{
	if(x <= 1.0f) {
		return (float)(x == 0 ? 0 : pow(2, 10 * x - 10));
	}

	return 1.0f;
}

float Ease_Out_Expo(float x)
{
	if(x <= 1.0f) {
		return (float)(x == 1 ? 1 : 1 - pow(2, -10 * x));
	}

	return 1.0f;
}

float Ease_InOut_Expo(float x)
{
	if(x <= 1.0f) {
		return (float)(x == 0
			? 0
			: x == 1
			? 1
			: x < 0.5 ? pow(2, 20 * x - 10) / 2
			: (2 - pow(2, -20 * x + 10)) / 2);
	}

	return 1.0f;
}


float Ease_In_Circ(float x)
{
	if(x <= 1.0f) {
		return (float)(1 - sqrt(1 - pow(x, 2)));
	}

	return 1.0f;
}

float Ease_Out_Circ(float x)
{
	if(x <= 1.0f) {
		return (float)(sqrt(1 - pow(x - 1, 2)));
	}

	return 1.0f;
}

float Ease_InOut_Circ(float x)
{
	if(x <= 1.0f) {
		return	(float)(x < 0.5
				? (1 - sqrt(1 - pow(2 * x, 2))) / 2
				: (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2);
	}

	return 1.0f;
}

float ApplyEasing2(float ratio, float value1, float value2, Easing easing)
{
	return value1 + (value2 - value1) * ApplyEasing1(ratio, easing);
}

float ApplyEasing1(float ratio, Easing easing)
{
	switch (easing)
	{
		case LINEAR:		return Linear(ratio);
		case IN_SINE:		return Ease_In_Sine(ratio);
		case IN_QUAD:		return Ease_In_Quad(ratio);
		case IN_CUBIC:		return Ease_In_Cubic(ratio);
		case IN_QUART:		return Ease_In_Quart(ratio);
		case IN_QUINT:		return Ease_In_Quint(ratio);
		case IN_EXPO:		return Ease_In_Expo(ratio);
		case IN_CIRC:		return Ease_In_Circ(ratio);
		case OUT_SINE:		return Ease_Out_Sine(ratio);
		case OUT_QUAD:		return Ease_Out_Quad(ratio);
		case OUT_CUBIC:		return Ease_Out_Cubic(ratio);
		case OUT_QUART:		return Ease_Out_Quart(ratio);
		case OUT_QUINT:		return Ease_Out_Quint(ratio);
		case OUT_EXPO:		return Ease_Out_Expo(ratio);
		case OUT_CIRC:		return Ease_Out_Circ(ratio);
		case INOUT_SINE:	return Ease_InOut_Sine(ratio);
		case INOUT_QUAD:	return Ease_InOut_Quad(ratio);
		case INOUT_CUBIC:	return Ease_InOut_Cubic(ratio);
		case INOUT_QUART:	return Ease_InOut_Quart(ratio);
		case INOUT_QUINT:	return Ease_InOut_Quint(ratio);
		case INOUT_EXPO:	return Ease_InOut_Expo(ratio);
		case INOUT_CIRC:	return Ease_InOut_Circ(ratio);
	}

	return Linear(ratio);
}
/*******************************************************************
	Internal Functions
*******************************************************************/