#include "Hurtbox.h"
#include "Damagable.h"
#include "transformable.h"
#include "transform.h"
#include "physics_entity.h"
#include "physics_world.h"
#include "collider.h"
#include "Layers.h"

static inline
void Internal_HurtboxDealDamage(const Hurtbox* self, List* colliders, float min_y, float max_y) {
    DamageEventData data = self->damage;
    list_foreach(Collider**, collider, colliders) {
        PhysicsEntity entity = collider_get_owner(*collider);
        const IDamagable* damagable = mirror_get_typeclass(entity.data, entity.mirror, "Damagable");
        const Transform* transform = entity.transformable->get_transform(entity.data);
        if(damagable && transform->position.y >= min_y && transform->position.y <= max_y) damagable->damage(entity.data, &data);
    }
}

int HurtboxCast(Hurtbox* self, float facing_dir) {
    const IPhysicsEntity* physics_entity = mirror_get_typeclass(self->owner.data, self->owner.mirror, "PhysicsEntity");
    const ITransformable* transformable = mirror_get_typeclass(self->owner.data, self->owner.mirror, "Transformable");

    if(physics_entity == NULL || transformable == NULL)
        return -1;

    RigidBody* body = physics_entity->get_rigidbody(self->owner.data);
    const Transform* transform = transformable->get_transform(self->owner.data);
    self->damage.origin = transform->position;

    const Vector offset = vaddf(transform->position, MakeVector(facing_dir * self->offset.x, self->offset.y));
    List found = physics_world_box_query_all(offset, self->size, PHYSICS_LAYER_COMBAT, body);
    Internal_HurtboxDealDamage(self, &found, transform->position.y - self->depth_extent, transform->position.y + self->depth_extent);
    return found.len;
}
