#include "vector.h"

#include <math.h>

// TODO: Implementation of all vector functions
vec3_t vec3_rotate_x(vec3_t v, float angle) {
    return (vec3_t) {
        .x = v.x,
        .y = v.y * cos(angle) - v.z * sin(angle),
        .z = v.y * sin(angle) + v.z * cos(angle),
    };
}

vec3_t vec3_rotate_y(vec3_t v, float angle) {
    return (vec3_t) {
        .x = v.x * cos(angle) - v.z * sin(angle),
        .y = v.y,
        .z = v.x * sin(angle) + v.z * cos(angle),
    };
}

vec3_t vec3_rotate_z(vec3_t v, float angle) {
    return (vec3_t) {
        .x = v.x * cos(angle) - v.y * sin(angle),
        .y = v.x * sin(angle) + v.y * cos(angle),
        .z = v.z,
    };
}

float vec2_length(const vec2_t vector) {
    return sqrt((vector.x * vector.x) + (vector.y * vector.y));
}

vec2_t vec2_add(const vec2_t a, const vec2_t b) {
    return (vec2_t) {
        .x = a.x + b.x,
        .y = a.y + b.y,
    };
}

vec2_t vec2_subtract(const vec2_t a, const vec2_t b) {
    return (vec2_t) {
        .x = a.x - b.x,
        .y = a.y - b.y,
    };
}

vec2_t vec2_multiply(const vec2_t vector, float scalar) {
    return (vec2_t) {
        .x = vector.x * scalar,
        .y = vector.y * scalar,
    };
}

vec2_t vec2_divide(const vec2_t vector, float scalar) {
    return (vec2_t) {
        .x = vector.x / scalar,
        .y = vector.y / scalar,
    };
}

float vec2_dot(const vec2_t a, const vec2_t b) {
    return (a.x * b.x) + (a.y * b.y);
}

float vec3_length(const vec3_t vector) {
    return sqrtf((vector.x * vector.x) + (vector.y * vector.y) + (vector.z * vector.z));
}

void vec2_normalize(vec2_t* vertex) {
    float length = vec2_length(*vertex);
    vertex->x /= length;
    vertex->y /= length;
}

vec3_t vec3_add(const vec3_t a, const vec3_t b) {
    return (vec3_t) {
        .x = a.x + b.x,
        .y = a.y + b.y,
        .z = a.z + b.z,
    };
}

vec3_t vec3_subtract(const vec3_t a, const vec3_t b) {
    return (vec3_t) {
        .x = a.x - b.x,
        .y = a.y - b.y,
        .z = a.z - b.z,
    };
}

vec3_t vec3_multiply(const vec3_t vector, const float scalar) {
    return (vec3_t) {
        .x = vector.x * scalar,
        .y = vector.y * scalar,
        .z = vector.z * scalar,
    };
}

vec3_t vec3_divide(const vec3_t vector, const float scalar) {
    return (vec3_t) {
        .x = vector.x / scalar,
        .y = vector.y / scalar,
        .z = vector.z / scalar,
    };
}

vec3_t vec3_cross(const vec3_t a, const vec3_t b) {
    return (vec3_t) {
        .x = a.y * b.z - a.z * b.y,
        .y = a.z * b.x - a.x * b.z,
        .z = a.x * b.y - a.y * b.x,
    };
}

float vec3_dot(const vec3_t a, const vec3_t b) {
    return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
}

void vec3_normalize(vec3_t* vertex) {
    float length = vec3_length(*vertex);
    vertex->x /= length;
    vertex->y /= length;
    vertex->z /= length;
}

vec4_t vec4_from_vec3(vec3_t vertex) {
    vec4_t ret;
    ret.x = vertex.x;
    ret.y = vertex.y;
    ret.z = vertex.z;
    ret.w = 1;

    return ret;
}

vec3_t vec3_from_vec4(vec4_t v) {
    return (vec3_t) {
        .x = v.x,
        .y = v.y,
        .z = v.z,
    };
}