#include <iostream>
#include <array>
#include "refl/uclass.h"
#include "vertex.h"
#include "tstring.h"
#include <functional>
using namespace std;
using namespace refl;
struct vec3_parent {

};
struct vec3 : public vec3_parent {
	using UClass = class vec3_UClass;
	float x = 1;
	float y = 2;
	float z = 3;
	string name{ "hellohellohellohellohellohello" };
	void norm(int x1) {
		x1 = x * y * z;
		cout << x1 << "::norm" << endl;
	}
	virtual float norm1(int x1) {
		cout << x1 << "::norm1" << endl;
		return x * y *z * x1;
	}
	static void norm2(int x1) {
		cout << x1 << "::norm2" << endl;
	}
	void norm3(int x1) {
		x1 = x * y * z;
		cout << x1 << "::norm3" << endl;
	}
};
struct vec3_UClass : public UClass {
public:
	array<FieldPtr,6> FList;
	using UClass::UClass;
	const FieldPtr* GetField(const Name& name)const override {
		for (auto& field : FList) {
			if (field.name == name) {
				return &field;
			}
		}
		return nullptr;
	}
	void InitObject(void* ptr)const override {
		vec3 obj{};
		std::construct_at((vec3*)ptr, obj);
	}
	static vec3_UClass BuildClass() {
		vec3_UClass cls(type_name<vec3>().View(), sizeof(vec3), &TypeInfo<vec3_parent>::StaticClass);
		//offsetof(vec3, x) 很坑，相当坑
		cls.FList[0] = cls.MakeMemberField<offsetof(vec3, x)>(&vec3::x, "x");
		cls.FList[1] = cls.MakeMemberField<offsetof(vec3, y)>(&vec3::y, "y");
		cls.FList[2] = cls.MakeMemberField<offsetof(vec3, z)>(&vec3::z, "z");
		cls.FList[3] = cls.MakeMethodField(&vec3::norm, "norm");
		cls.FList[4] = cls.MakeMethodField(&vec3::norm1, "norm1");
		cls.FList[5] = cls.MakeMethodField(&vec3::norm2, "norm2");
		return cls;
	}
};
int main() {
	auto& cls = TypeInfo<vec3>::StaticClass;
	auto ptr1 = &vec3::norm;
	auto ptr2 = &vec3::norm1;
	auto ptr3 = &vec3::norm2;
	auto ptr4 = &vec3::norm3;
	vec3 v;
	using Any = void*;
	ObjectView pv(&v, &cls);
	//using ClassMethod = void(Any::*)(int);
	using MethodType = void(void*, int);
	MethodType* ptr_wrap = (MethodType*)*(void**)&ptr1;
	pv.Invoke("norm", 10);
 	ptr_wrap(&v, 10);
	ptr_wrap = (MethodType*)*(void**)&ptr2;
	float x;
	pv.InvokeRet("norm1",x ,10);
	ptr_wrap(&v, 10);
	ptr_wrap = (MethodType*)*(void**)&ptr3;
	pv.Invoke("norm2", 10);
	ptr_wrap(&v, 10);
	ptr_wrap = (MethodType*)*(void**)&ptr4;
	ptr_wrap(&v, 10);
	PrintHex8(ptr1);
	PrintHex8(ptr2);
	PrintHex8(ptr3);
	PrintHex8(ptr4);
	cout << "hello world\n";
}