using UnityEngine;
using System.Collections;

public enum EASING_TYPE { LINEAR, EXPO_EASE_IN, EXPO_EASE_IN_OUT, EXPO_EASE_OUT, CUBIC_EASE_IN, CUBIC_EASE_OUT, CUBIC_EASE_IN_OUT };

public class Utils : MonoBehaviour
{
	private static Utils _instance;
	public static Utils shared { get{ return _instance; } }
	
	public static string Md5Sum(string strToEncrypt)
 {
  System.Text.UTF8Encoding ue = new System.Text.UTF8Encoding();
  byte[] bytes = ue.GetBytes(strToEncrypt);
  
  // encrypt bytes
  System.Security.Cryptography.MD5CryptoServiceProvider md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
  byte[] hashBytes = md5.ComputeHash(bytes);
  
  // Convert the encrypted bytes back to a string (base 16)
  string hashString = "";
  
  for (int i = 0; i < hashBytes.Length; i++)
  {
   hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, '0');
  }
  
  return hashString.PadLeft(32, '0');
 }
	
	void Awake()
	{
		_instance = this;	
	}
	
	public static float Map(float value, float inputMin, float inputMax, float outputMin, float outputMax, bool clamp)
	{
		return Map(value, inputMin, inputMax, outputMin, outputMax, clamp, EASING_TYPE.LINEAR);	
	}
	
	public static float Map(float value, float inputMin, float inputMax, float outputMin, float outputMax, bool clamp, EASING_TYPE easingType)
	{
		float ratio = (value - inputMin) / (inputMax - inputMin);
		
		switch(easingType)
		{
		case EASING_TYPE.EXPO_EASE_IN:
			ratio = ExpoEaseIn(ratio);
			break;
		case EASING_TYPE.EXPO_EASE_IN_OUT:
			ratio = ExpoEaseInOut(ratio);
			break;
		case EASING_TYPE.EXPO_EASE_OUT:
			ratio = ExpoEaseOut(ratio);
			break;
		case EASING_TYPE.CUBIC_EASE_IN:
			ratio = CubicEaseIn(ratio);
			break;
		case EASING_TYPE.CUBIC_EASE_OUT:
			ratio = CubicEaseOut(ratio);
			break;
		case EASING_TYPE.CUBIC_EASE_IN_OUT:
			ratio = CubicEaseInOut(ratio);
			break;
		default:
			break;
		}
		
		float outVal = outputMin + (ratio * (outputMax - outputMin));
		
		if(clamp)
		{
			if(outputMax < outputMin)
			{
				if( outVal < outputMax )outVal = outputMax;
				else if( outVal > outputMin )outVal = outputMin;
			}
			else
			{
				if( outVal > outputMax )outVal = outputMax;
				else if( outVal < outputMin )outVal = outputMin;
			}
		}
		
		return outVal;
	}
	
	public static Vector2 GetVectorFromRotation(float degrees)
	{
		float x = Mathf.Sin(-degrees * Mathf.Deg2Rad);
		float y = Mathf.Cos(degrees * Mathf.Deg2Rad);
		return new Vector2(x, y);
	}
	
	public static float GetRotationFromVector(Vector2 vector)
	{
		return (Mathf.Atan2(vector.y, vector.x) - Mathf.Atan2(Vector2.up.y, Vector2.up.x));
	}
		
	public static Color GetColorFromRGB255(int r, int g, int b)
	{
		return new Color((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, 1.0f);
	}
	
	public static Color GetColorFromRGB255(int r, int g, int b, float a)
	{
		return new Color((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, a);
	}
	
	public static float ExpoEaseIn(float t)
	{
		return Mathf.Pow(2.0f, 10.0f * (t - 1.0f));
	}
	
	public static float ExpoEaseOut(float t)
	{
		return 1.0f - Mathf.Pow(2.0f, -10.0f * t);
	}
	
	public static float ExpoEaseInOut(float t)
	{
		return (t < 0.5f) ? ExpoEaseIn(t * 2.0f) * 0.5f : 1 - ExpoEaseIn(2.0f - t * 2.0f) * 0.5f;
	}
	
	public static float CubicEaseIn(float t)
	{
		return t * t * t;
	}
	
	public static float CubicEaseOut(float t)
	{
		return 1.0f - CubicEaseIn(1.0f - t);
	}
	
	public static float CubicEaseInOut(float t)
	{
		return (t < 0.5f) ? CubicEaseIn(t * 2.0f) * 0.5f : 1.0f - CubicEaseIn(2.0f - t * 2.0f) * 0.5f;
	}
}
