#ifndef _fencer_transform_h
#define _fencer_transform_h

#include "vmath.h"
#include "transformable.h"

typedef struct Transform Transform;
struct Transform {
    Vector position;
    Vector scale;
    float rotation;
};

#define IdentityTransform (Transform){ZeroVector, OneVector, 0.0f}

static inline Transform transform_apply(Transform parent, Transform child);
static inline Transform transform_invert(Transform a);
static inline Vector transform_direction(Transform* self, Vector direction);
static inline Vector transform_point(Transform* self, Vector point);

static inline
Transform transform_apply(Transform parent, Transform child) {
    return (Transform) {
        .position = transform_point(&parent, child.position),
        .scale = vmulf(parent.scale, child.scale),
        .rotation = parent.rotation + child.rotation
    };
}

static inline
Transform transform_invert(Transform a) {
    return (Transform) {
        .position = vinvf(a.position),
        .scale = vreciprocalf(a.scale),
        .rotation = -a.rotation
    };
}

static inline
Vector transform_direction(Transform* self, Vector direction) {
    return vrotatef(direction, self->rotation);
}

static inline
Vector transform_point(Transform* self, Vector position) {
    return vaddf(vmulf(vrotatef(position, self->rotation), self->scale), self->position);
}

static inline
Vector inverse_transform_point(Transform* self, Vector position) {
    return vrotatef(vmulf(vsubf(position, self->position), vreciprocalf(self->scale)), -self->rotation);
}

static
Transform* transform_get_transform(Transform* self) {
    return self;
}

impl_Transformable_for(Transform,
    transform_get_transform
);

#endif // !_fencer_transform_h