#pragma once

#define NOMINMAX

#include <glew.h>
#include <wglew.h>
#include <iostream>
#include <algorithm> 
#include <limits>
#include <sstream>

#define PI 3.14159265358979323846f
#define DEGREES(x) ((x) * (180.0f / PI))
#define RADIANS(x) ((x) * (PI / 180.0f))

#define BLOCKDIMENSION (1<<3)
#define BLOCKDIMENSIONLOD(x) (BLOCKDIMENSION >> x)

#define BLOCKSIZE (BLOCKDIMENSION*BLOCKDIMENSION*BLOCKDIMENSION)
#define BLOCKSIZELOD(x) (BLOCKDIMENSIONLOD(x)*BLOCKDIMENSIONLOD(x)*BLOCKDIMENSIONLOD(x))

#define BLOCKOFFSET(x) ((8*BLOCKSIZE * ((1<<(3*x))-1) ) / (7 * (1<<(3*x))))
#define BLOCKMEMORY (unsigned int((8*BLOCKSIZE)/7))


template<class Type>
inline const bool IsPowerOfTwo(const Type & tNumber)
{
	return ((tNumber&(tNumber-1))==0);
}

template<class Type>
inline const Type GetNextPowerOfTwo(const Type & tNumber)
{
	Type tPowerOfTwo = 1;

	while (tPowerOfTwo < tNumber)
		tPowerOfTwo = tPowerOfTwo * 2;

	return tPowerOfTwo;
}

template <class Type>
inline GLenum glInternalFormat();

template <class Type>
inline GLenum glFormat();

template <class Type>
inline GLenum glType();

template <>
inline GLenum glType<char>()
{
	return GL_BYTE;
};

template <>
inline GLenum glType<unsigned char>()
{
	return GL_UNSIGNED_BYTE;
};

template <>
inline GLenum glType<short>()
{
	return GL_SHORT;
};

template <>
inline GLenum glType<unsigned short>()
{
	return GL_UNSIGNED_SHORT;
};

template <>
inline GLenum glType<int>()
{
	return GL_INT;
};

template <>
inline GLenum glType<unsigned short>()
{
	return GL_UNSIGNED_INT;
};

template <>
inline GLenum glType<float>()
{
	return GL_FLOAT;
};

template <>
inline GLenum glType<double>()
{
	return GL_DOUBLE;
};

template <class Type>
inline const Type fromString(const std::string & strString)
{
	Type tValue;
	std::stringstream(std::string(strString)) >> tValue;		
	return tValue;
};

template <class Type>
inline const std::string toString(const Type & tValue)
{
	std::stringstream ss;
	ss << tValue;
	return ss.str();
};

inline const std::string trimLeft( const std::string &str, const std::string &strWhitespace = "\n\r\t ")
{
	size_t uIndex = str.find_first_not_of(strWhitespace);
	if( uIndex != std::string::npos )
		return str.substr(uIndex);

	return "";
};

inline const std::string trimRight( const std::string &str, const std::string &strWhitespace = "\n\r\t ")
{
	size_t  uIndex = str.find_last_not_of(strWhitespace);
	if( uIndex != std::string::npos )
		return str.substr(0,uIndex+1);

	return str;
};

inline const std::string trim( const std::string &str, const std::string & strWhitespace = "\n\r\t ")
{
	return trimRight(trimLeft(str,strWhitespace),strWhitespace);
};


