/*
 * $Id: common.h 4789 2017-11-24 13:40:52Z antonin.misek-skoda-auto.cz $
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


#ifndef __COMMON_H__
#define __COMMON_H__

#include "VrutApi.h"

#ifdef WIN_X64
#pragma warning(disable:4005) ///Disable warning for macro redefinition in windef.h and glut.h in x64
#endif

///Smallest distinguishable value
const float EPSILON = 1e-5f;

#include <wx/string.h>
#include <wx/arrstr.h>
//#define WIN32_LEAN_AND_MEAN

#define NO_DEFAULT_CONSTRUCTOR(class_name)			class_name()
#define NO_COPY_CONSTRUCTOR(class_name)				class_name(const class_name &)
#define NO_ASSIGN_OPERATOR(class_name)				class_name &operator =(const class_name &)

// Some interfaces (pure abstract classes) are designed in a way that they will never be deleted,
// or more precisely, function "delete" will never be called on a pointer to that interface,
// instead, delete will always be called on a pointer to a class implementing that interface.
// These interfaces do not need virtual destructors.
// NO_DESTRUCTOR_INTERFACE ensures two things:
//	1) It hides the destructor, so that it can be called only from derived classes. Thanks to this,
//		noone can delete an object using a point to the interface (in debug builds).
//	2) It does not define the destructor, so it adds no additional method/function into the
//		interface (in release builds).
// To use it, place it in the protected block of the interface, with the name of the interface
// as its parameter, e.g.:
//	class MyInterface
//	{
//	protected:
//		NO_DESTRUCTOR_INTERFACE(MyInterface);
//	public:
//		...
//	};
#ifdef _DEBUG
#define NO_DESTRUCTOR_INTERFACE(class_name)			~class_name() {}
#else
#define NO_DESTRUCTOR_INTERFACE(class_name)
#endif

/// Use GLOBAL_CONST to define constants in header files to avoid linker errors. When the linker
/// finds two or more symbols defined as GLOBAL_CONST, it should choose only a single one and
/// discard the others. Example of usage:
///			GLOBAL_CONST float MY_PI = 3.14f;
#ifdef __WXMSW__
#define GLOBAL_CONST extern const __declspec(selectany)
#else
#define GLOBAL_CONST extern const __attribute__((weak))
#endif

template <class T_out, class T_in>
inline T_out SafeStaticCast(T_in ptr_in)
{
	T_out ptr_out = static_cast<T_out>(ptr_in);
	assert(!ptr_in || dynamic_cast<T_out>(ptr_in));		// If this failed so did the static cast one line above
	return ptr_out;
}

#ifdef __WINDOWS__
	#define DLLIMPORT __declspec(dllimport)
	#define DLLEXPORT __declspec(dllexport)
	#include "float.h"
	#define cpuid(info,x, y)    __cpuidex(info,x,y)

	/// Align the address of a variable to N bytes
	#define VRUT_ALIGNED(N)		__declspec(align(N))

	/// Allocates memory aligned to given alignment. The memory must be freed using VrutAlignedFree
	inline void *VrutAlignedMalloc(size_t size, size_t alignment)
	{
		return _aligned_malloc(size, alignment);
	}
	/// Frees memory allocated by VrutAlignedMalloc
	inline void VrutAlignedFree(void *ptr)
	{
		_aligned_free(ptr);
	}

#else
	#define DLLIMPORT __attribute__ ((visibility("default")))
	#define DLLEXPORT
	#define __max(a,b) (((a) > (b)) ? (a) : (b))
	#define __min(a,b) (((a) < (b)) ? (a) : (b))
	#define _strnicmp strncasecmp
	#define _isnan std::isnan
	#define _finite finite
	#define __forceinline inline
	#define MAXDWORD 0xffffffff
	//  GCC Inline Assembly
	void cpuid(int CPUInfo[4], int InfoType, int ECXValue);

	// Align the address of a variable to N bytes
	#define VRUT_ALIGNED(N)		__attribute__((aligned(N)))

	/// Allocates memory aligned to given alignment. The memory must be freed using VrutAlignedFree
	inline void *VrutAlignedMalloc(size_t size, size_t alignment)
	{
		void *result;
		posix_memalign(&result, alignment, size);
		return result;
	}
	/// Frees memory allocated by VrutAlignedMalloc
	inline void VrutAlignedFree(void *ptr)
	{
		free(ptr);
	}
#endif

#define SAFE_DELETE(a)\
	{if (a)\
		delete (a);\
	(a) = NULL;}

#define SAFE_DELETE_ARR(a)\
	{if (a)\
		delete [] (a);\
	(a) = NULL;}

#define SAFE_DELETE_ARR_EACH(a, cnt)\
	for (unsigned _xx_ = 0; _xx_ < (cnt); _xx_++)\
		SAFE_DELETE((a)[_xx_])

#define SAFE_RELEASE(a)\
	{if (a)\
		(a)->Release();}

///Allowed \c true values
const wxString TRUE_STRINGS[] = { wxT("true"), wxT("enable"), wxT("enabled"), wxT("on"), wxT("yes"), wxT("1") };
const size_t TRUE_STRINGS_COUNT = 6;
const unsigned GL_ID_NONE = (unsigned)~(unsigned(0));

///Clone \c wxString
//TODO: Use wxString::Clone in wxWidgets 2.9.0
inline wxString CloneWxString(const wxString & str)
{
	/*wxString cloned(str);
	return cloned;*/
	return str;
}

///Check if given string is one of defined true values
inline bool isTrue(const wxString & val)
{
	for (size_t i = 0; i < TRUE_STRINGS_COUNT; i++)
		if (val.IsSameAs(TRUE_STRINGS[i], false))
			return true;
	return false;
}

///Round float number
inline int roundVR(float x)
{
	return int(x > 0.0f ? x + 0.5f : x - 0.5f);
}

///Round double number
inline int roundVR(double x)
{
	return int(x > 0.0 ? x + 0.5 : x - 0.5);
}

#define USE_MERSENNE_TWISTER 1

#if USE_MERSENNE_TWISTER
#include "MersenneTwister.h"
extern VRUT_CORE_API MTRand mtrand;
#endif

///Random generator with limits (included)
inline int random(int min, int max)
{
#if USE_MERSENNE_TWISTER
  return mtrand.randInt(max - min) + min;
#else
  return rand()%(max-min) + min;
#endif
}

///Random generator with limits (included)
inline float random(float min, float max)
{
#if USE_MERSENNE_TWISTER
  return (float)mtrand.rand(max - min) + min;
#else
	return float(rand())/RAND_MAX * (max - min) + min;
#endif
}

///Random generator with limits (included)
inline double random(double min, double max)
{
#if USE_MERSENNE_TWISTER
  return mtrand.rand(max - min) + min;
#else
	return double(rand())/RAND_MAX * (max - min) + min;
#endif
}

///find best choice for ComboBox (mainly usefull when value is not equal to any string)
static size_t FindBestMatch(const wxArrayString &choices, const wxString &value)
{
	size_t bestMatch = (size_t)-1;
	for (size_t i = 0; i < choices.size(); i++)
	{
		if (choices[i] == value)
			return i;
		if (choices[i].substr(0, value.size()) == value)
			bestMatch = i;
	}
	return bestMatch;
}

///Macros for custom warning writing
///Using:
///#pragma message __WARNING_LOC__"your warning message"
#define __QUOTE_STR2__(x) #x
#define __QUOTE_STR1__(x) __QUOTE_STR2__(x)
#define __WARNING_LOC__ __FILE__ "(" __QUOTE_STR1__(__LINE__) ") : warning: "

#include "3dmath.h"

#endif
