#pragma once
#include <array>
#include "uclass.h"
namespace refl {
	template<_ReflCheck_Ctor T>
	class UClass_Auto : public UClass {
	public:
		using UClass::UClass;
		using MyUClass = UClass_Auto<T>;
	public:
		consteval 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>;
			}
			else {
				cls.flag = CLASS_TRIVIAL_FLAG;
			}
			return cls;
		}
		void Set(void* ptr,const T& t) {
			*(T*)ptr = t;
		}
		T& Get(void* ptr) {
			return *(T*)ptr;
		}
	};

	/*
	* 模板优化
	* 成员参数转化为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() };
		}
		//这里顺序似乎是不确定的，但是我实际运用是对的
		//如果使用make_index_sequence,会多一次函数调用
		//为什么包裹一层迭代器，就不会出现警告了
		static void Call(const FieldPtr* field, const sarray<ArgsView>& ArgsList) {
			assert(sizeof...(Args) <= ArgsList.size());
			if constexpr (std::is_same_v<R, void>) {
				MethodType fptr = (MethodType)field->data.method;
				auto param = ArgsList.end();
				fptr((param--->cast_to<Args>())...);
			}
			else {
				MethodType fptr = (MethodType)field->data.method;
				auto param = ArgsList.end();
				auto ret = ArgsList.get();
				if (ret->cls == &TypeInfo<R*>::StaticClass) {
					*(R*)ret->val = fptr((param--->cast_to<Args>())...);
				}
				else {
					fptr((param--->cast_to<Args>())...);
				}
			}
		}
	protected:
		consteval 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<std::remove_cv_t<std::remove_pointer_t<Args>>*>::StaticClass, ptr++));
			}
		}
	public:
		//为了简化判断，cls 对象 统统指向 T*
		consteval static MyUClass BuildClass() {
			MyUClass cls(type_name<MethodType>().View(), sizeof(MethodType));
			cls.vtable.GetParams = &MyUClass::GetParams;
			cls.vtable.Call = &MyUClass::Call;
			cls.flag = CLASS_TRIVIAL_FLAG;
			cls.BuildUList();
			return cls;
		}
	};
	template<typename T, typename P = void>
	class UClass_Meta : public UClass {
	public:
		using FieldsType = decltype(T::__MakeFields());
		FieldsType Fields{ T::__MakeFields() };
		UClass_Meta() : UClass(type_name<T>().View(), sizeof(T)){
			if constexpr (std::is_trivially_copyable_v<T>) {
				flag = CLASS_TRIVIAL_FLAG;
			}
			if constexpr (!std::is_same_v<P, void>) {
				parent = &TypeInfo<P>::StaticClass;
			}
			if constexpr (has_init_object<T>::value) {
				vtable.InitObject = &T::__InitObject;
			}
			else {
				vtable.InitObject = &UClass::InitObject<T>;
			}
		}
		const FieldPtr* GetField(int index) const {
			return &Fields[index];
		}
		const FieldPtr* GetField(const Name& name, int index = 0) const{
			constexpr int length = std::tuple_size<FieldsType>::value;
			auto ptr = index < length ? &Fields[index] : nullptr;
			for (int i = index; i < length; i++, ptr++) {
				if (name == ptr->name) {
					return ptr; 
				}
			}
			return nullptr;
		} 
	};

	//基础类型的偏特化
	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();
	};
}