#pragma once
#include "UTemplate/Type.hpp"
#include "../std/sarray.h"
#include <variant>
#include <functional>
using Ubpa::Name;
using Ubpa::type_name;
namespace refl {
	class UClass;
	class ArgsView;
	class ArgsValue;

	using Offset = uint32_t;
	using Method = void*;

	using DefaultMember = const ArgsView (*)();
	using DefaultMethod = std::pair<ArgsView*, int>(*)();

	enum FieldFlag:uint32_t {
		FIELD_NONE_FLAG				= 0,
		FIELD_MEMBER_FLAG			= 1 << 0,
		FIELD_ATTRIBUTE_FLAG		= 1 << 1,
		FIELD_METHOD_FLAG			= 1 << 2,
		FIELD_METHOD_VALUE_FLAG     = 1 << 3
	};
	struct FieldPtr {
		union Data
		{
			Offset offset;
			Method method;
			constexpr Data() : method(nullptr) {}
			constexpr Data(Offset& offset) : offset(offset) {}
			constexpr Data(Method& method) : method(method) {}
			constexpr Data(const Method& method) : method(method) {}
		};
		union Default {
			DefaultMember member;
			DefaultMethod method;
			constexpr Default(): method(nullptr) {}
			constexpr Default(DefaultMember& member) : member(member) {}
			constexpr Default(DefaultMethod& method) : method(method) {}
		};
		Name name;
		const UClass* type{};
		Data data{};
		Default value{};
		uint32_t flag{};
		
		//unsafe
		bool Invoke(const sarray<ArgsView>& ArgsList)const;
		//safe
		bool Invoke(std::vector<ArgsView>& ArgsList)const;

		template<typename Func, typename... Args>
		auto Call(Func func, Args&&... args)const;

		std::vector<const UClass*> GetParams() const;
	};
	template<typename T, typename R, typename ...Args>
	consteval auto fetch_method_t(R(T::*)(Args...)) {
		using MethodType = R(*)(const void*, Args...);
		return MethodType{ nullptr };
	}
	template<typename R, typename ...Args>
	consteval auto fetch_method_t(R(*)(Args...)) {
		using MethodType = R(*)(Args...);
		return MethodType{ nullptr };
	}
	template<typename T>
	consteval int fetch_args_size() {
		auto fields = T::__MakeStaticFields();
		int size = 0;
		for (auto& field : fields) {
			size += field.data.offset;
		}
		return size;
	}
	template<typename T>
	class Field;
	/*
	template<typename T, typename V>
	consteval V* fetch_member_v(V T::*) {
		return nullptr;
	}
	template<typename R, typename T, typename ...Args>
	consteval auto fetch_method_v(R (T::* ptr)(Args...)) {
		using MethodType = R(*)(T*, Args...);
		return MethodType{nullptr};
	}
	template<typename R, typename ...Args>
	consteval auto fetch_method_v(R(*ptr)(Args...)) {
		return ptr;
	}
	template<typename... Args>
	consteval auto FetchMembers(const std::tuple<Args...>&) {
		return std::make_tuple(fetch_member_v(Args{nullptr})...);
	}
	template<typename... Args>
	consteval auto FetchMethods(const std::tuple<Args...>&) {
		return std::make_tuple(fetch_method_v(Args{ nullptr })...);
	}
	template<typename ...Args>
	class FieldMembers{
	public:
		constexpr FieldMembers() {}
		FieldMembers(const std::tuple<Args*...>&) {

		}
		constexpr static int GetSize() {
			return sizeof...(Args);
		}
	};
	template<typename ...Args>
	class FieldMethods{
	public:
		constexpr FieldMethods() {}
		FieldMethods(const std::tuple<Args*...>&) {

		}
		constexpr static int GetSize() {
			return sizeof...(Args);
		}
	};*/
}