#ifndef RTTI_H
#define RTTI_H

struct RuntimeClass
{
	RuntimeClass(const char* classname);
	RuntimeClass(const char* classname, const RuntimeClass* baseTypeInfo);

	bool IsKindOf(const RuntimeClass* typeInfo) const;

	const char* Name() const;

	const RuntimeClass* m_baseRuntimeClass;
	const char* m_classname;
};

#define DECLARE_RTTI_ROOT(typeName) \
	public: \
		static const RuntimeClass s_runtimeClass; \
		static const RuntimeClass* GetStaticRuntimeClass() { return &s_runtimeClass; } \
		virtual const RuntimeClass* GetRuntimeClass() const { return GetStaticRuntimeClass();  }

#define DECLARE_RTTI(typeName, baseTypeName) \
	public: \
		static const RuntimeClass s_runtimeClass; \
		static const RuntimeClass* GetStaticRuntimeClass() { return &s_runtimeClass; } \
		virtual const RuntimeClass* GetRuntimeClass() const { return GetStaticRuntimeClass();  }

#define IMPLEMENT_RTTI_ROOT(typeName) \
	const RuntimeClass typeName::s_runtimeClass(#typeName, nullptr)

#define IMPLEMENT_RTTI(typeName, baseTypeName) \
	const RuntimeClass typeName::s_runtimeClass(#typeName, baseTypeName::GetStaticRuntimeClass())

template <typename T>
const RuntimeClass* GetRuntimeClass()
{
	return T::GetStaticRuntimeClass();
}

#define RUNTIME_CLASS(typeName) (typeName::GetStaticRuntimeClass())

#endif //!RTTI_H