#include "DeerStudio/StudioAPI/Math.h"
#include "DeerStudio/AngelScriptEngine/AngelScriptRegisters.h"

namespace Deer {
	void AngelScriptEngine::registerMathStructs() {
		AS_CHECK(scriptEngine->RegisterObjectType("vec3", sizeof(glm::vec3), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<glm::vec3>() | asOBJ_APP_CLASS_ALLFLOATS));
		AS_CHECK(scriptEngine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(StudioAPI::vec3_constructor), asCALL_CDECL_OBJLAST));
		AS_CHECK(scriptEngine->RegisterObjectBehaviour("vec3", asBEHAVE_CONSTRUCT, "void f(float, float = 0, float = 0)", asFUNCTION(StudioAPI::vec3_constructor_params), asCALL_CDECL_OBJLAST));
		AS_CHECK(scriptEngine->RegisterObjectProperty("vec3", "float x", asOFFSET(glm::vec3, x)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("vec3", "float y", asOFFSET(glm::vec3, y)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("vec3", "float z", asOFFSET(glm::vec3, z)));

		AS_CHECK(scriptEngine->RegisterObjectType("quat", sizeof(glm::quat), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<glm::quat>() | asOBJ_APP_CLASS_ALLFLOATS));
		AS_CHECK(scriptEngine->RegisterObjectProperty("quat", "float x", asOFFSET(glm::quat, x)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("quat", "float y", asOFFSET(glm::quat, y)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("quat", "float z", asOFFSET(glm::quat, z)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("quat", "float w", asOFFSET(glm::quat, w)));

		AS_CHECK(scriptEngine->RegisterObjectType("Transform", sizeof(TransformComponent), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<TransformComponent>()));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Transform", "vec3 position", asOFFSET(TransformComponent, position)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Transform", "vec3 scale", asOFFSET(TransformComponent, scale)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Transform", "quat rotation", asOFFSET(TransformComponent, rotation)));

		AS_CHECK(scriptEngine->RegisterObjectType("Camera", sizeof(CameraComponent), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<CameraComponent>()));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Camera", "float fov", asOFFSET(CameraComponent, fov)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Camera", "float aspect", asOFFSET(CameraComponent, aspect)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Camera", "float nearZ", asOFFSET(CameraComponent, nearZ)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("Camera", "float farZ", asOFFSET(CameraComponent, farZ)));

		AS_CHECK(scriptEngine->RegisterObjectType("SceneCamera", sizeof(SceneCamera), asOBJ_VALUE | asOBJ_POD | asGetTypeTraits<SceneCamera>()));
		AS_CHECK(scriptEngine->RegisterObjectProperty("SceneCamera", "Camera camera", asOFFSET(SceneCamera, camera)));
		AS_CHECK(scriptEngine->RegisterObjectProperty("SceneCamera", "Transform transform", asOFFSET(SceneCamera, transform)));
	}

	void AngelScriptEngine::registerMathFunctions() {
		REGISTER_EXT_OBJECT_METHOD("vec3", "vec3 opAdd(const vec3 &in)", StudioAPI::vec3_add);
		REGISTER_EXT_OBJECT_METHOD("vec3", "vec3 opSub(const vec3 &in) const", StudioAPI::vec3_sub);
		REGISTER_EXT_OBJECT_METHOD("vec3", "vec3 opNeg() const", StudioAPI::vec3_neg);
		REGISTER_EXT_OBJECT_METHOD("vec3", "vec3 opMul(float) const", StudioAPI::vec3_mult);
		REGISTER_EXT_OBJECT_METHOD("vec3", "vec3 opMul_r(float) const", StudioAPI::vec3_mult);

		REGISTER_EXT_OBJECT_CONSTRUCTOR("quat", "void f()", StudioAPI::quat_construct);
		REGISTER_EXT_OBJECT_CONSTRUCTOR("quat", "void f(float, float, float, float)", StudioAPI::quat_constructFromValue);
		REGISTER_EXT_OBJECT_DESTRUCTOR("quat", "void f()", StudioAPI::quat_destruct);

		REGISTER_EXT_OBJECT_METHOD("quat", "quat opMul(const quat &in) const", StudioAPI::quat_multiply);
		REGISTER_EXT_OBJECT_METHOD("quat", "vec3 getEuler() const", StudioAPI::quat_getEuler);
		REGISTER_EXT_OBJECT_METHOD("quat", "void setEuler(vec3)", StudioAPI::quat_setEuler);

		REGISTER_EXT_OBJECT_CONSTRUCTOR("Transform", "void f()", StudioAPI::transform_construct);
		REGISTER_EXT_OBJECT_CONSTRUCTOR("Camera", "void f()", StudioAPI::camera_construct);
		REGISTER_EXT_OBJECT_CONSTRUCTOR("SceneCamera", "void f()", StudioAPI::sceneCamera_Construct);

		REGISTER_EXT_OBJECT_METHOD("Transform", "vec3 relative(vec3)", StudioAPI::transform_relative);
	}
} // namespace Deer
