#pragma once

#define CLASS_TYPE_STRUCTS_VERSION 1
#include <string.h>
#include "other.hpp"

struct RTTI_Complete_Object_Locator;
struct RTTI_Class_Hierarchy_Descriptor;
struct RTTI_Base_Class_Descriptor;
struct RTTI_Type_Descriptor;

struct RTTI_Complete_Object_Locator
{
	void* signature;
	void* offset;
	void* cdOffset;
	RTTI_Type_Descriptor* RTTI_Type_Descriptor;
	RTTI_Class_Hierarchy_Descriptor* RTTI_Class_Hierarchy_Descriptor;
};

struct RTTI_Class_Hierarchy_Descriptor
{
	void* signature;
	void* attributes;
	void* numBaseClasses;
	void* BaseClassArray;
};

struct RTTI_Base_Class_Descriptor
{
	RTTI_Type_Descriptor* RTTI_Type_Descriptor;
	unsigned int* numContainedBases;
	void* mdisp;
	void* pdisp;
	void* vdisp;
	void* attributes;
	RTTI_Class_Hierarchy_Descriptor* RTTI_Class_Hierarchy_Descriptor;
};

struct RTTI_Type_Descriptor
{
	void* pVFTable;
	void* spare;
	char name[]; //null-terminated, indefinite length
};

//RTII_instanceOf((ADDR*)objADDR, ".?AV" "BitStream" "@@");
//Useful for non-ConsoleObject (non-SimObject) classes that aren't exposed to TorqueScript
int RTII_instanceOf(unsigned int* obj, const char* className)
{
	if(obj == NULL)
		return -1;

	//RTTI_Complete_Object_Locator is located right behind vftable
	ADDR* vftable_meta_ptr = (ADDR*)(*obj - 4);
	if(vftable_meta_ptr == NULL)
		return -2;


	RTTI_Complete_Object_Locator* Complete_Object_Locator = (RTTI_Complete_Object_Locator*)(*vftable_meta_ptr);

	if(Complete_Object_Locator == NULL)
		return -3;


	RTTI_Class_Hierarchy_Descriptor* Class_Hierarchy_Descriptor = Complete_Object_Locator->RTTI_Class_Hierarchy_Descriptor;

	if(Class_Hierarchy_Descriptor == NULL)
		return -4;


	ADDR* Base_Class_Array = (ADDR*)(Class_Hierarchy_Descriptor->BaseClassArray);

	if(Base_Class_Array == NULL)
		return -5;

	//loop until pointer is 0
	for(unsigned int i = 0; Base_Class_Array[i] != 0; i++)
	{
		RTTI_Base_Class_Descriptor* Base_Class_Descriptor = (RTTI_Base_Class_Descriptor*)Base_Class_Array[i];

		if(Base_Class_Descriptor->RTTI_Type_Descriptor == NULL)
			continue;

		//.?AV is a C++ class
		//@@ at end is terminal

		char* testName = Base_Class_Descriptor->RTTI_Type_Descriptor->name;
		if(strcmp(className, testName) == 0)
			return 1;
	}

	return 0;
}


