#include "Prop.h"
#include "debug.h"
#include "game_world.h"
#include "mirror.h"
#include "physics_world.h"

START_REFLECT(Prop)
    REFLECT_TYPECLASS(Prop, Transformable)
    REFLECT_TYPECLASS(Prop, Drop)
    REFLECT_TYPECLASS(Prop, BehaviourEntity)
END_REFLECT(Prop)

impl_Transformable_for(Prop,
    PropGetTransform
)

impl_PhysicsEntity_for(Prop,
    PropGetRigidBody,
    PropOnCollision,
    PropOnOverlap
)

impl_Drop_for(Prop,
    DestroyProp
)

impl_BehaviourEntity_for(Prop,
    PropStart,
    PropUpdate,
    PropDraw,
    PropGetDepth
)

Prop* MakeProp(Sprite* sprite, Shape* shape) {
    Prop* self = malloc(sizeof(Prop));
    ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for Prop instance");
    *self = (Prop) {
        .transform = IdentityTransform,
        .sprite = sprite,
        .rigidbody = NULL,
        .collisionShape = NULL
    };
    self->rigidbody = rigidbody_make(Prop_as_PhysicsEntity(self));
    self->collisionShape = collider_new(Prop_as_PhysicsEntity(self), shape, 0, PHYSICS_LAYER_DEFAULT, PHYSICS_LAYER_DEFAULT);
    rigidbody_set_static(self->rigidbody, 1);
    sprite_set_origin(self->sprite, MakeVector(0.5f, 1.0f));
    return self;
}

Prop* SpawnProp(Vector location, Sprite* sprite, Shape* shape, Vector origin) {
    Prop* self = MakeProp(sprite, shape);
    
    self->transform.position
        = rigidbody_get_transform(self->rigidbody)->position
        = location;

    game_world_add_entity(Prop_as_BehaviourEntity(self));
    physics_world_add_entity(Prop_as_PhysicsEntity(self));
    
    sprite_set_origin(self->sprite, origin);
        
    return self;
}

void DestroyProp(Prop* self) {
    sprite_destroy(self->sprite);
    physics_world_remove_entity(Prop_as_PhysicsEntity(self));
    collider_destroy(self->collisionShape);
    rigidbody_destroy(self->rigidbody);
    free(self);
}

void PropStart(Prop* self) {}
void PropUpdate(Prop* self, float deltaTime) {}

void PropDraw(Prop* self) {
    sprite_draw(self->sprite, self->transform);
}

void PropOnCollision(Prop* self, Collision collision) {}
void PropOnOverlap(Prop* self, Collider* other) {}

Transform* PropGetTransform(Prop* self) {
    return &self->transform;
}

RigidBody* PropGetRigidBody(Prop* self) {
    return self->rigidbody;
}
