#pragma once

#include <stdio.h>

typedef enum
{
	PointerMRStatsAddressType,
	ObjectMRStatsAddressType
} MRStatsAddressType;

#undef Start_Registering
#undef Stop_Registering
#undef Register_Object
#undef Register_Pointer
#undef Unregister_Object
#undef Unregister_Pointer
#undef Object_Registration
#undef Check_All_Signatures

#if !defined(MEMORY_REGISTER)
	#define Start_Registering()
	#define Start_Registering()
	#define Stop_Registering()
	#define Register_Object(address) Check(address)
	#define Register_Pointer(address) Check_Pointer(address)
	#define Unregister_Object(address) Check(address)
	#define Unregister_Pointer(address) Check_Pointer(address)
	#define Object_Registration(address)
	#define Check_All_Signatures()
#else
	extern void Start_Registering_Function();
	extern void	Stop_Registering_Function();

	extern void	Register_Pointer_Function(void *address, MRStatsAddressType address_type, char *file_name, int line_num);
	extern void	Unregister_Pointer_Function(void *address, char *file_name, int line_num);

	extern void	Object_Registration_Function(void *address, char *file_name, int line_num);

	extern void Check_All_Signatures_Function(char *file_name, int line_num);

	#define Start_Registering() Start_Registering_Function()
	#define Stop_Registering() Stop_Registering_Function()

	#define Check_All_Signatures() Check_All_Signatures_Function(__FILE__, __LINE__)

	#if defined(MEMORY_VERIFY)
		#undef Check
		#define Check(p)\
		{\
			Check_Signature(p);\
			Verify((p)->TestInstance());\
			Check_All_Signatures();\
		}
	#endif

	#define Register_Object(address)\
	{\
		Check(address);\
		Register_Pointer_Function(\
			address,\
			Is_Signature_Bad((Signature*)address) ?\
				PointerMRStatsAddressType : ObjectMRStatsAddressType,\
			__FILE__, __LINE__\
		);\
	}

	#define Register_Pointer(address) Register_Pointer_Function(address, PointerMRStatsAddressType, __FILE__, __LINE__)
	#define Unregister_Object(address)\
	{\
		Check(address);\
		Unregister_Pointer_Function(address, __FILE__, __LINE__);\
	}
	
	#define Unregister_Pointer(address)		Unregister_Pointer_Function(address, __FILE__, __LINE__)
	#define Object_Registration(address)	Object_Registration_Function(address, __FILE__, __LINE__)
#endif
