#pragma once

#include <math.h>
#include <d3dx9.h>
#include "..\DXFunctions\DXVector3.h"

#define SAFEDELETEARRAY(ptr)	{if(ptr){delete [] ptr;ptr=NULL;}}
#define SAFEDELETE(ptr)			{if(ptr){delete ptr;ptr=NULL;}}
#define SAFERELEASE(ptr)		{if(ptr){ptr->Release();ptr=NULL;}}

//#define SETPROPERTY(type,membername) inline void Set##membername(type value){m_##membername = value;}
//#define GETPROPERTY(type,membername) inline type Get##membername(void){return m_##membername;}
//#define GETSETPROPERTY(type,membername) SETPROPERTY(type,membername) GETPROPERTY(type,membername)

#define DEGtoRAD(angle)		((float)angle*D3DX_PI/180.f)

#define NOTNAN(x) (x>0||x<=0)
#define ISNAN(x) (!(x>0)&&!(x<=0))

#define SIGN(x) (x>0?1:(x<0?-1:0))

//inline float DEGtoRAD(float a)
//{
//	return (float)a*D3DX_PI/180.f;
//}

#define _min(a,b) (((a) < (b)) ? (a) : (b))
#define _max(a,b) (((a) > (b)) ? (a) : (b))

DXVector3 DecomposeRollPitchYaw(D3DXMATRIX mat);

void OrthonormalizeOrientation(D3DXMATRIX&mat);

inline float frand(void)
{
	return rand()/(float)RAND_MAX;
}

inline float sfrand(void) 
{
	return ((rand()/(float)RAND_MAX) - 0.5f)*2.f;
}

inline unsigned F2DW( float f )
{
	return *((unsigned*)&f);
}

inline float logn(const float base, const float x)
{
	return log(x) / log(base);
}

inline int sgn(const float n) //signum function
{
	return n < 0 ? -1 : (n > 0 ? 1 : 0);
}

//inline float Cubic_Interpolate(float v0,float v1,float v2,float v3,float x)
inline float Cubic_Interpolate(const float&v0,const float&v1,const float&v2,const float&v3,const float&x)
{
	float P = (v3 - v2) - (v0 - v1);
	//float Q = (v0 - v1) - P;
	float xx = x*x;
	//return P*pow(x,3.f) + Q*pow(x,2.f) + R*x + S;
	return P*xx*x + ((v0-v1)-P)*xx + (v2 - v0)*x + v1;
}

inline float Linear_Interpolate(const float&a,const float&b,const float&x)
{
	return  a*(1-x) + b*x;
}

inline float Cosine_Interpolate(const float&a,const float&b,const float&x)
{
	float ft = x * D3DX_PI;
	float f = (1 - cos(ft)) * 0.5f;
	return  a*(1.f-f) + b*f;
}

//returns a normal-"verteilten" randomvalue
//should not be used without any clamping
inline float NormVert(float muh,float sigma)
{
	//var rnd = Math.random()*2. - 1.;
	//return (muh + Math.pow(Math.abs(rnd),exp)*sigma*rnd/Math.abs(rnd));
	//return muh + Math.pow(Math.abs(rnd,Math.E)*Math.PI*sigma;
	return muh + sqrt(-2*log(frand())) * cos(2*D3DX_PI*frand()) * sigma;
}

inline float QuadVert(float min,float max)
{
	return min + (max-min) * frand();
}

inline unsigned ARGB32(BYTE a,BYTE r,BYTE g,BYTE b)
{
	return (a<<24)+(r<<16)+(g<<8)+b;
}

class DXRessource
{
protected:
	bool m_bInvalidated;

	virtual void DoRestore(void) {}
	virtual void DoInvalidate(void) {}

	DXRessource(void) { m_bInvalidated = true; }
	virtual ~DXRessource(void) { }

public:
	void Restore(void)
	{ 
		if(m_bInvalidated)
		{ 
			DoRestore(); 
			m_bInvalidated = false;
		}
	}

	void Invalidate(void)
	{ 
		if(!m_bInvalidated)
		{ 
			DoInvalidate(); 
			m_bInvalidated = true;
		} 
	}
};

class Ressource
{
protected:
	int m_RefCount;

	Ressource(void) { m_RefCount = 1; }
	virtual ~Ressource(void) {}

public:
	
	void IncRefCount(void) { m_RefCount++; }

	void Release(void) 
	{ 
		if (--m_RefCount <= 0) 
			delete this; 
	}
};