#pragma once

#include <stdio.h>

#if !defined(DEBUG_STREAM)
	#define DEBUG_STREAM std::cout
#endif

#if !defined(Verify)
	#if !defined(DEBUG_LEVEL)
		#define DEBUG_LEVEL 0
	#endif
	#if DEBUG_LEVEL<1
		#include "debugoff.h"
	#elif DEBUG_LEVEL<2
		#include "debug1on.h"
	#elif DEBUG_LEVEL<3
		#include "debug2on.h"
	#else
		#include "debug3on.h"
	#endif
#endif

#if defined(__BCPLUSPLUS__)
	extern int _matherr(struct exception *a);
#endif

extern int Fpu_Ok();
extern void Verify_Failed(char *message, char *file, int line);
//extern void	Fail_To_Debugger(char *message, char *file, int line);
//extern void	PostQuitMessage(int exit_code);

class Signature
{
private:
#if DEBUG_LEVEL>0
	enum Mark
	{
		ok,
		destroyed,
		corrupted,
		noMagic=(int)0xAB135795L,
		magic=(int)0xFFED1231L
	} mark;
#endif

protected:
	Signature();
	~Signature();

public:
	friend int Is_Signature_Bad(const volatile Signature *p);
};

#if defined(USE_SIGNATURE)
	#define SIGNATURED : public Signature
#else
	#define SIGNATURED
	#define Is_Signature_Bad(p) (false)
#endif

//#############
//# MACROS    #
//#############

#define ELEMENTS(Array)		(sizeof(Array)/sizeof(*Array))

#if defined(TEST_CLASS)
	#define Test(c)\
		if (!(c))\
		{\
		DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\
		return false;\
		}

	#define Test_And_Dump(c, v)\
		if (!(c))\
		{\
			DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\
			DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#v" = " << (v) << '\n';\
			return false;\
		}

	#define Test_Message(m)		(DEBUG_STREAM << m)

	#define Test_Branch_On()	Fail("First visit of branch")
	#define Test_Branch_Off()	
#else
	#define Test(c)
	#define Test_And_Dump(c,v)
	#define Test_Message(m)
#endif

//################
//# ENUMERATIONS #
//################

enum
{
	False = 0,
	True  = 1
};

//###########
//# CASTING #
//###########

#define SKIPPY_CAST(Type,var)	(*((Type*)&(var)))

//#############
//# TEMPLATES #
//#############

//#include <crtdbg.h>

#define SMALL				(1e-4f)

#define Abs(value) ((value>0) ? value : -value)
#define Clamp(v,f,c) (v = ((v<f) ? f : ((v>c) ? c : v)))
#define Max_Clamp(v,c) (v = ((v>c) ? c : v))
#define Is_Many_Bits(value) (Lowbit(value)^value)
#define Low_Bit(value) (value & (-value))
#define Min_Clamp(v,f) (v = ((v<f) ? f : v))
#define Max(a,b) ((a>b) ? a : b)
#define Min(a,b) ((a<b) ? a : b)
#define Sgn(value) ((value<-SMALL) ? -1 : value>SMALL)

//############
//# TYPEDEFS #
//############

typedef int					Logical;
typedef unsigned __int8		Byte;
typedef unsigned __int16	Word;
typedef unsigned __int32	LWord;

typedef int Enumeration;

#include "memreg.h"