#include "mesh_render_entity.h"
#include "render.h"

START_REFLECT(MeshRenderEntity);
REFLECT_TYPECLASS(MeshRenderEntity, Drop);
REFLECT_TYPECLASS(MeshRenderEntity, SceneNodeEntity);
REFLECT_TYPECLASS(MeshRenderEntity, Renderable);
END_REFLECT(MeshRenderEntity);

impl_SceneNodeEntity_defaults(MeshRenderEntity)
impl_SceneNodeEntity_for(MeshRenderEntity,
    MeshRenderEntityEnterTree,
    MeshRenderEntityExitTree,
    MeshRenderEntity_default_tick
)

impl_Drop_for(MeshRenderEntity,
    DestroyMeshRenderEntity
)

impl_Renderable_for(MeshRenderEntity,
    MeshRenderEntityDraw
)

SceneNode *CreateMeshRenderEntity(char const *resource_path) {
    MeshRenderEntity *self = new(MeshRenderEntity);
    GetModelResource(resource_path, &self->model);
    GetShaderResource("default_shader", &self->shader);
    return CreateSceneNode(MeshRenderEntity_as_SceneNodeEntity(self));
}

void DestroyMeshRenderEntity(MeshRenderEntity *self) {
    free(self);
}

void MeshRenderEntityEnterTree(MeshRenderEntity *self) {
    SceneNodeEntity parent_entity = self->node->parent->entity;
    self->transform = TC_CAST(parent_entity, Transformable);
    LoadResource(self->model.handle);
    LoadResource(self->shader.handle);
    for(size_t i = 0; i < self->model.resource->materialCount; ++i)
        self->model.resource->materials[i].shader = *self->shader.resource;
    AddRenderable(MeshRenderEntity_as_Renderable(self));
}

void MeshRenderEntityExitTree(MeshRenderEntity *self) {
    ReleaseResource(self->model.handle);
    ReleaseResource(self->shader.handle);
    RemoveRenderable(MeshRenderEntity_as_Renderable(self));
}

void MeshRenderEntityDraw(MeshRenderEntity *self) {
    self->model.resource->transform = TransformGetMatrix(self->transform.tc->get_global_transform(self->transform.data));
    BeginShaderMode(*self->shader.resource);
    DrawModel(*self->model.resource, Vector3Zero(), 1.0f, WHITE);
    EndShaderMode();
}
