#ifndef TRANSFORMABLE_H
#define TRANSFORMABLE_H

#include "scene.h"
#include "utils/mirror.h"
#include "utils/typeclass_helpers.h"
#include "raylib.h"
#include "raymath.h"

typedef struct ITransformable {
    SceneNode *node;
    Transform *(*const get_transform)(void*);
    Transform *(*const get_global_transform)(void*);
} ITransformable;

typedef struct Transformable {
    ITransformable const *tc;
    void *data;
    IMirror const *mirror;
} Transformable;

extern Transform TransformIdentity();
extern Matrix TransformGetMatrix(Transform const *self);
extern void UpdateTransformable(Transformable *self, Transformable *parent);

#define impl_Transformable_for(T, get_transform_f, get_global_transform_f)\
Transformable T##_as_Transformable(T *x) {\
    TC_FN_TYPECHECK(Transform *,get_transform_f, T*);\
    TC_FN_TYPECHECK(Transform *,get_global_transform_f, T*);\
    static ITransformable const tc = {\
        .get_transform        = (Transform *(*const)(void*)) get_transform_f,\
        .get_global_transform = (Transform *(*const)(void*)) get_global_transform_f\
    };\
    return (Transformable){ .tc = &tc, .data = x, .mirror = T##_as_Mirror(x).tc };\
}

#endif // !TRANSFORMABLE_H
