#ifndef _update_entity_h
#define _update_entity_h

#include "drop.h"
#include "typeclass_helpers.h"
#include "vmath.h"

typedef struct {
    void (*const update)(void* self, float dt);
    void (*const start)(void* self);
    void (*const draw)(void* self);
    long (*const get_depth)(void* self);
} IEntityBehaviour;

typedef struct {
    void* data;
    IEntityBehaviour const* tc;
    IDrop const* drop;
} BehaviourEntity;

#define impl_BehaviourEntity_for(T, start_f, update_f, draw_f, get_depth_f)\
static inline BehaviourEntity T##_as_BehaviourEntity(T* x) {\
    TC_FN_TYPECHECK(void, start_f, T*);\
    TC_FN_TYPECHECK(void, update_f, T*, float);\
    TC_FN_TYPECHECK(void, draw_f, T*);\
    TC_FN_TYPECHECK(long, get_depth_f, T*);\
    static IEntityBehaviour const tc = {\
        .update =  (void(*const)(void*, float))  update_f,\
        .start =   (void(*const)(void*))         start_f,\
        .draw =    (void(*const)(void*))         draw_f,\
        .get_depth=(long(*const)(void*))         get_depth_f,\
    };\
    TC_FN_TYPECHECK(Drop, T##_as_Drop, T*);\
    IDrop const* drop = T##_as_Drop(x).tc;\
    return (BehaviourEntity){.tc = &tc, .drop = drop, .data = x};\
}\

#endif // !_update_entity_h
