#pragma once
#include "uclass.h"
namespace refl {
	template<typename Func, typename... Args>
	inline auto FieldPtr::Call(Func func, Args&& ...args)const
	{
		using MemberFunc = decltype(fetch_method_t(func));
		MemberFunc fptr = (MemberFunc)data.method.fptr;
		return fptr(std::forward<Args>(args)...);
	}
	inline bool FieldPtr::Invoke(const sarray<Any>& ArgsList)const{
		auto Call = type->vtable.Call;
		if (Call) {
			Call(this, ArgsList);
		}
		return Call;
	}
	inline bool FieldPtr::Invoke(svector<Any>& ArgsList)const {
		auto Call = type->vtable.Call;
		if (Call) {
			sarray<const UClass*> params = GetParams();
			int paramsSize = params.size();
			int argsSize = ArgsList.size();
			if (argsSize < paramsSize && flag & FIELD_METHOD_VALUE_FLAG) {
				const Any* argsPtr = data.method.value.front();
				int valueSize = data.method.value.size();
				if (argsSize + valueSize >= paramsSize) {
					for (int i = valueSize + argsSize - paramsSize; i < valueSize; i++) {
						ArgsList.push_back(*(argsPtr + i));
					}
					argsSize = paramsSize;
				}
			}
			if (argsSize < paramsSize) {
				return false;
			}
			auto a = ArgsList.front();
			auto p = params.front();
			for (auto e = params.back(); p < e; ++p, ++a) {
				if (a->cls != *p && !a->Check(*p)) {
					return false;
				}
			}
			Call(this, ArgsList);
		}
		return Call;
	}
	template<typename SArgsList>
	inline bool FieldPtr::Invokes(SArgsList& ArgsList)const {
		auto Call = type->vtable.Call;
		if (Call) {
			sarray<const UClass*> params = GetParams();
			if (params.size() != ArgsList.size()) {
				return false;
			}
			auto a = ArgsList.front();
			auto p = params.front();
			for (auto e = params.back(); p < e; ++p, ++a) {
				if (a->cls != *p && !a->Check(*p)) {
					return false;
				}
			}
			Call(this, ArgsList);
		}
		return false;
	}
	inline sarray<const UClass*> FieldPtr::GetParams() const {
		auto GetParams = type->vtable.GetParams;
		if (GetParams) {
			return GetParams(type);
		}
		return{};
	}
}