#include "vector.h"
#include <math.h>

////////////////////////////////////////////////////////////////////////////////
// implementations of vector 2d functions
////////////////////////////////////////////////////////////////////////////////
float vec2_length(vec2_t v) {
    return sqrt(v.x * v.x + v.y * v.y); 
}

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

    return result;
}

vec2_t vec2_sub(vec2_t a, vec2_t b) {
    vec2_t result = {
        .x = a.x - b.x,
        .y = a.y - b.y,
    };
    
    return result; 
}

vec2_t vec2_mul(vec2_t v, float factor) {
    vec2_t result = {
        .x = v.x * factor,
        .y = v.y * factor
    };

    return result;
}

vec2_t vec2_div(vec2_t v, float factor) {
    vec2_t result = {
        .x = v.x / factor,
        .y = v.y / factor
    };

    return result;
}

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

void vec2_normalize(vec2_t* v) {
    // Get length by squaring x and y, adding together and taking sqrt
    float length = sqrt((v->x * v->x) + (v->y * v->y));
    v->x /= length; // directly modifies x and y no need to return
    v->y /= length;
}

////////////////////////////////////////////////////////////////////////////////
// implementations of vector 3d functions
////////////////////////////////////////////////////////////////////////////////
float vec3_length(vec3_t v) {
    return sqrt(v.x * v.x + v.y * v.y + v.z * v.z); 
}

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

    return result;
}

vec3_t vec3_sub(vec3_t a, vec3_t b) {
    vec3_t result = {
        .x = a.x - b.x,
        .y = a.y - b.y,
        .z = a.z - b.z
    };

    return result;
}

vec3_t vec3_mul(vec3_t v, float factor) {
    vec3_t result = {
        .x = v.x * factor,
        .y = v.y * factor,
        .z = v.z * factor
    };

    return result;
}

// Division
vec3_t vec3_div(vec3_t v, float factor) {
    vec3_t result = {
        .x = v.x / factor,
        .y = v.y / factor,
        .z = v.z / factor
    };

    return result;
}

// Cross Product - helps to find perpendicular vector between two vectors
vec3_t vec3_cross(vec3_t a, vec3_t b) {
    vec3_t result = {
        .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
    }; 
    return result;
}

// Dot Product - helps to find how aligned two vectors are to eachother
float vec3_dot(vec3_t a, vec3_t b) {
    return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);

}

// Normalize a vec3_t vector
void vec3_normalize(vec3_t* v) {
    float length = sqrt((v->x * v->x) + (v->y * v->y) + (v->z * v->z));
    v->x /= length;
    v->y /= length;
    v->z /= length;
}

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

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

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

////////////////////////////////////////////////////////////////////////////////
// implementations of vector conversion functions
////////////////////////////////////////////////////////////////////////////////
vec4_t vec4_from_vec3(vec3_t v) {
    vec4_t result = { v.x, v.y, v.z, 1.0 };
    return result;
}

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

vec2_t vec2_from_vec4(vec4_t v) {
    vec2_t result = { v.x, v.y };
    return result;
}


/*
vec3_t cube_vertice[8] = {
    { .x = -1, .y = -1, .z = -1 },  // 1
    { .x = -1, .y =  1, .z = -1 },  // 2
    { .x =  1, .y =  1, .z = -1 },  // 3
    { .x =  1, .y = -1, .z = -1 },  // 4
    { .x =  1, .y =  1, .z =  1 },  // 5
    { .x =  1, .y = -1, .z =  1 },  // 6
    { .x = -1, .y =  1, .z =  1 },  // 7
    { .x = -1, .y = -1, .z =  1 }   // 8  
};*/

/*
face_t cube_faces[12] = {
    // front
    { .a = 1, .b = 2, .c = 3 },
    { .a = 1, .b = 3, .c = 4 },
    // right
    { .a = 4, .b = 3, .c = 5 },
    { .a = 4, .b = 5, .c = 6 },
    // back
    { .a = 6, .b = 5, .c = 7 },
    { .a = 6, .b = 7, .c = 8 },
    // left
    { .a = 8, .b = 7, .c = 2 },
    { .a = 8, .b = 2, .c = 1 },
    // top
    { .a = 2, .b = 7, .c = 5 },
    { .a = 2, .b = 5, .c = 3 },
    // bottom
    { .a = 6, .b = 8, .c = 1 },
    { .a = 6, .b = 1, .c = 4 }
};*/
