// Math Helper Class
// Provides access to a number of mathematical functions.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public static class MathHelper
{
	delegate float FalloffFunction(float Falloff_Distance, float Value);
	private static Dictionary<Falloff,FalloffFunction> FalloffFunctions = new Dictionary<Falloff, FalloffFunction>
	{
		{Falloff.Logarithmic,	Logarithmic},
		{Falloff.Constant,		Constant},
		{Falloff.Linear, 		Linear},
		{Falloff.Quadratic,		Quadratic},
		{Falloff.Cubic,			Cubic},
		{Falloff.Hectic,		Hectic},
		{Falloff.Sinusoidal,	Sinusoidal},
		{Falloff.Cosinusoidal,	Cosinusoidal}
	};
	
	///Returns a value using the Falloff type provided, scaled using the distance and range provided.
	///This is used mainly for calculating splash damage reduction for explosions.
	static public float DoFalloff(Falloff functionType, float Falloff_Distance, float Falloff_Range)
	{
		return FalloffFunctions[functionType](Falloff_Distance, Falloff_Range);
	}
	
	private static float Logarithmic(float x, float y)
	{
		float output = Mathf.Log(y,x);
		return output;
	}
	
	private static float Constant(float x, float y)
	{
		return x < y? 1:0;
	}
	
	private static float Linear(float x, float y)
	{
		return x < y? 1 - (x/y) : 0;
	}
	
	private static float Quadratic(float x, float y)
	{
		return x < y? Mathf.Pow(1-(x/y),2) : 0;
	}
	
	private static float Cubic(float x, float y)
	{
		return x < y? Mathf.Pow(1-(x/y),3) : 0;
	}
	
	private static float Hectic(float x, float y)
	{
		return x < y? Mathf.Pow(1-(x/y),100) : 0;
	}
	
	private static float Sinusoidal(float x, float y)
	{
		return Mathf.Max(x < y? Mathf.Sin(x) : 0 , 0);
	}
	
	private static float Cosinusoidal(float x, float y)
	{
		return Mathf.Max(x < y? Mathf.Cos(x) : 0, 0);
	}
	
	///For use with the ModifierType enum. This is used to select and perform a operation based on an enum.
	public static float Modifier(ModifierType m, float BaseValue, float ModifierValue)
	{
		switch(m)
		{
		case ModifierType.Additive:
			return BaseValue + ModifierValue;
		case ModifierType.Divider:
			return BaseValue / ModifierValue;
		case ModifierType.Multiplier:
			return BaseValue * ModifierValue;
		case ModifierType.Power:
			return Mathf.Pow(BaseValue, ModifierValue);
		case ModifierType.Subtractive:
			return BaseValue - ModifierValue;
		}
		return BaseValue;
	}
	
	///Recursive summative application of an ascending power on a value
	///Useful for calculating diminishing returns
	public static float PowR(float baseValue, float multiplier, int count)
	{
		return PowR (0, baseValue, multiplier, count);
	}
	
	public static float PowR(float previousValue, float baseValue, float multiplier, int count)
	{
		previousValue += baseValue * Mathf.Pow(multiplier, count);
		if (count > 0)
		{
			return PowR (previousValue, baseValue, multiplier, count -1);
		}
		return previousValue;
	}
}
