#include "camera_node.h"
#include "utils/debug.h"

START_REFLECT(CameraNode);
REFLECT_TYPECLASS(CameraNode, Drop);
REFLECT_TYPECLASS(CameraNode, Transformable);
REFLECT_TYPECLASS(CameraNode, SceneNodeEntity);
END_REFLECT(CameraNode);

impl_Drop_for(CameraNode,
    DestroyCameraNode
)
impl_Transformable_for(CameraNode,
    CameraNodeGetTransform,
    CameraNodeGetGlobalTransform
)

impl_SceneNodeEntity_defaults(CameraNode);
impl_SceneNodeEntity_for(CameraNode,
    CameraNodeEnterTree,
    CameraNode_default_exit_tree,
    CameraNode_default_tick
)

SceneNode *CreateCameraNode() {
    CameraNode *camera_node = new(CameraNode);
    camera_node->transform = TransformIdentity();
    camera_node->global_transform = TransformIdentity();
    camera_node->node = NULL;
    return CreateSceneNode(CameraNode_as_SceneNodeEntity(camera_node));
}

void DestroyCameraNode(CameraNode *self) {
    SceneNodeDetachEntity(self->node);
    free(self);
}

void CameraNodeEnterTree(CameraNode *self) {
    if(self->node->scene->main_camera == NULL) {
        self->node->scene->main_camera = self;
        LOG_INFO("CameraNodeEnterTree");
    }
}

Camera3D CameraNodeGetCamera(CameraNode *self) {
    Matrix mat = TransformGetMatrix(&self->global_transform);
    Vector3 forward = { mat.m8, mat.m9, mat.m10 };
    LOG_INFO("Forward: %f, %f, %f", forward.x, forward.y, forward.z);
    return (Camera3D){
        .fovy = 90,
        .position = self->global_transform.translation,
        .projection = CAMERA_PERSPECTIVE,
        .target = Vector3Add(self->global_transform.translation, Vector3Scale(forward, 1000.f)),
        .up = (Vector3){mat.m4, mat.m5, mat.m6}
    };
}

Transform *CameraNodeGetTransform(CameraNode *self) { return &self->transform; }
Transform *CameraNodeGetGlobalTransform(CameraNode *self) { return &self->global_transform; }
