#pragma once
#include "uclass.h"
namespace refl {
	template<_ReflCheck_Ctor T>
	class UClass_Auto : public UClass {
	public:
		using UClass::UClass;
		using MyUClass = UClass_Auto<T>;
	public:
		constexpr static MyUClass BuildClass() {
			MyUClass cls(type_name<T>().View(), sizeof(T));
			if constexpr (!std::is_trivially_copyable_v<T>) {
				cls.vtable.InitObject = &MyUClass::InitObject<T>;
				cls.vtable.CopyObject = &MyUClass::CopyObject<T>;
			}
			return cls;
		}
	};

	/*
	* 模板优化
	* 成员参数转化为const void*
	* 引用参数转化为指针
	*/
	template<typename R, typename... Args>
	class UMethod_Auto : public UClass {
		using UClass::UClass;
		using MethodType = R(*)(Args...);
		using MyUClass = UMethod_Auto<R, Args...>;
	public:
		std::array<const UClass*, sizeof...(Args) + 1> UList{};

		static std::vector<const UClass*> GetParams(const UClass* cls) {
			auto& UList = static_cast<const MyUClass*>(cls)->UList;
			return { UList.data(), UList.data() + UList.size() };
		}
		static void Call(const FieldPtr& field, std::vector<ArgsView>& ArgsList) {
			if constexpr (std::is_same_v<R, void>) {
				MethodType fptr = (MethodType)field.data.method;
				auto param = ArgsList.rbegin();
				fptr(param++->cast_to<Args>()...);
			}
			else {
				MethodType fptr = (MethodType)field.data.method;
				auto param = ArgsList.rbegin();
				auto ret = ArgsList.begin();
				if (ret->cls == &TypeInfo<R>::StaticClass) {
					*(R*)ret->val = fptr(param++->cast_to<Args>()...);
				}
				else {
					fptr(param++->cast_to<Args>()...);
				}
			}
		}
	protected:
		constexpr void BuildUList() {
			if constexpr (!std::is_same_v<R, void>) {
				UList[0] = &TypeInfo<R>::StaticClass;
			}
			if constexpr (sizeof...(Args) > 0) {
				auto ptr = &UList[1];
				(..., (*ptr = &TypeInfo<typename std::remove_pointer_t<Args>*>::StaticClass, ptr++));
			}
		}
	public:
		//为了简化判断，cls 对象 统统指向 T*
		constexpr static MyUClass BuildClass() {
			MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
			cls.vtable.GetParams = &MyUClass::GetParams;
			cls.vtable.Call = &MyUClass::Call;
			cls.BuildUList();
			return cls;
		}
	};
	class UClass_Custom : public UClass {
	public:
		using UClass::UClass;
		std::vector<FieldPtr> FList{};
		int32_t AttrNum{ 0 };

		static const FieldPtr* GetField(const UClass* _cls,const Name& name, bool isMethod){
			auto cls = static_cast<const UClass_Custom*>(_cls);
			auto& FList = cls->FList;
			// 指定开始位置的迭代器
			auto start = FList.begin();
			if (isMethod) {
				start += cls->AttrNum;
			}
			auto end = FList.end();
			for (auto it = start; it != end; ++it) {
				if (it->name == name) {
					return &*it;
				}
			}
			return nullptr;
		}
		/*
		void BuildClass() {
			FList.shrink_to_fit();//缩减容量，FList大小不再改变了
			vtable.GetField = &UClass_Custom::GetField;
		}
		*/
	};
	//基础类型的偏特化
	template<_ReflCheck_Ctor_NoUClass T>
	struct TypeInfoImpl<T> {
		using UClass = UClass_Auto<T>;
		inline constexpr static UClass StaticClass = UClass::BuildClass();
	};

	// 函数指针类型的偏特化
	template<typename R, typename... Args>
	struct TypeInfoImpl<R(*)(Args...)> {
		using UClass = UMethod_Auto<R, Args...>;
		inline constexpr static UClass StaticClass = UClass::BuildClass();
	};

	template<_ReflCheck_UClass T>
	struct TypeInfoImpl<T> {
		using MyUClass = typename T::MyUClass;
		inline static MyUClass StaticClass = []()->MyUClass {
			MyUClass cls(type_name<T>().View(), sizeof(T));
			T::BuildClass(cls);
			auto& vtable = cls.vtable;
			if (!vtable.GetField) {
				vtable.GetField = &MyUClass::GetField;
			}
			if constexpr (!std::is_trivially_copyable_v<T>) {
				if (!vtable.InitObject) {
					//这里一定会创建一个InitObject<T> 模板函数，如何优化
					vtable.InitObject = &UClass::InitObject<T>;
				}
				if (!vtable.CopyObject) {
					//这里一定会创建一个CopyObject<T> 模板函数，如何优化
					vtable.CopyObject = &UClass::CopyObject<T>;
				}
			}
			return cls;
		}();
	};
}