#ifndef JNR_VEC2_H
#define JNR_VEC2_H

#include <math.h>

typedef struct Vec2 {
    float x, y;
} Vec2;

static inline Vec2 vec2(float x, float y) {
    return (Vec2){ x, y };
}

static inline Vec2 vec2_zero(void) {
    return (Vec2){ 0.0f, 0.0f };
}

static inline Vec2 vec2_add(Vec2 a, Vec2 b) {
    return (Vec2){ a.x + b.x, a.y + b.y };
}

static inline Vec2 vec2_sub(Vec2 a, Vec2 b) {
    return (Vec2){ a.x - b.x, a.y - b.y };
}

static inline Vec2 vec2_scale(Vec2 v, float s) {
    return (Vec2){ v.x * s, v.y * s };
}

static inline float vec2_dot(Vec2 a, Vec2 b) {
    return a.x * b.x + a.y * b.y;
}

static inline float vec2_len(Vec2 v) {
    return sqrtf(v.x * v.x + v.y * v.y);
}

static inline float vec2_len_sq(Vec2 v) {
    return v.x * v.x + v.y * v.y;
}

static inline Vec2 vec2_norm(Vec2 v) {
    float len = vec2_len(v);
    if (len < 0.0001f) return vec2_zero();
    return vec2_scale(v, 1.0f / len);
}

static inline Vec2 vec2_lerp(Vec2 a, Vec2 b, float t) {
    return (Vec2){
        a.x + (b.x - a.x) * t,
        a.y + (b.y - a.y) * t
    };
}

static inline float vec2_dist(Vec2 a, Vec2 b) {
    return vec2_len(vec2_sub(a, b));
}

static inline Vec2 vec2_clamp(Vec2 v, Vec2 min, Vec2 max) {
    Vec2 r;
    r.x = v.x < min.x ? min.x : (v.x > max.x ? max.x : v.x);
    r.y = v.y < min.y ? min.y : (v.y > max.y ? max.y : v.y);
    return r;
}

static inline float clampf(float v, float min, float max) {
    return v < min ? min : (v > max ? max : v);
}

static inline float lerpf(float a, float b, float t) {
    return a + (b - a) * t;
}

static inline float signf(float v) {
    return (v > 0.0f) - (v < 0.0f);
}

static inline float absf(float v) {
    return v < 0.0f ? -v : v;
}

#endif /* JNR_VEC2_H */
