/*
  Copyright (c) 2014 Alex Diener
  
  This software is provided 'as-is', without any express or implied
  warranty. In no event will the authors be held liable for any damages
  arising from the use of this software.
  
  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:
  
  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.
  
  Alex Diener adiener@sacredsoftware.net
*/

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

bool Vector2f_normalize(Vector2f * vector) {
	float magnitude;
	
	magnitude = sqrtf(vector->x * vector->x + vector->y * vector->y);
	if (magnitude > 0.0f) {
		vector->x = vector->x / magnitude;
		vector->y = vector->y / magnitude;
		return true;
	}
	return false;
}

Vector2f Vector2f_normalized(Vector2f vector) {
	Vector2f_normalize(&vector);
	return vector;
}

float Vector2f_magnitude(Vector2f vector) {
	return sqrtf(vector.x * vector.x + vector.y * vector.y);
}

float Vector2f_magnitudeSquared(Vector2f vector) {
	return vector.x * vector.x + vector.y * vector.y;
}

float Vector2f_distance(Vector2f vector1, Vector2f vector2) {
	return Vector2f_magnitude(Vector2f_subtract(vector1, vector2));
}

float Vector2f_distanceSquared(Vector2f vector1, Vector2f vector2) {
	return Vector2f_magnitudeSquared(Vector2f_subtract(vector1, vector2));
}

bool Vector2f_scaleTo(Vector2f * vector, float magnitude) {
	if (Vector2f_normalize(vector)) {
		*vector = Vector2f_multiplyScalar(*vector, magnitude);
		return true;
	}
	return false;
}

Vector2f Vector2f_scaledTo(Vector2f vector, float magnitude) {
	Vector2f_scaleTo(&vector, magnitude);
	return vector;
}

Vector2f Vector2f_add(Vector2f vector1, Vector2f vector2) {
	return VECTOR2f(vector1.x + vector2.x, vector1.y + vector2.y);
}

Vector2f Vector2f_subtract(Vector2f vector1, Vector2f vector2) {
	return VECTOR2f(vector1.x - vector2.x, vector1.y - vector2.y);
}

Vector2f Vector2f_multiplyScalar(Vector2f vector, float scalar) {
	return VECTOR2f(vector.x * scalar, vector.y * scalar);
}

Vector2f Vector2f_divideScalar(Vector2f vector, float scalar) {
	return VECTOR2f(vector.x / scalar, vector.y / scalar);
}

Vector2f Vector2f_interpolate(Vector2f left, Vector2f right, float value) {
	return VECTOR2f(left.x * (1.0f - value) + right.x * value,
	                left.y * (1.0f - value) + right.y * value);
}

Vector2f Vector2f_reflect(Vector2f vector, Vector2f normal) {
	Vector2f result;
	float dot;
	
	dot = Vector2f_dot(vector, normal);
	result.x = vector.x - 2.0f * dot * normal.x;
	result.y = vector.y - 2.0f * dot * normal.y;
	return result;
}

Vector2f Vector2f_project(Vector2f vector, Vector2f normal) {
	float dot;
	
	dot = Vector2f_dot(vector, normal);
	vector.x -= normal.x * dot;
	vector.y -= normal.y * dot;
	return vector;
}

Vector2f Vector2f_rotate(Vector2f vector, float radians) {
	Vector2f result;
	
	result.x = vector.x * cosf(radians) + vector.y * -sinf(radians);
	result.y = vector.x * sinf(radians) + vector.y *  cosf(radians);
	return result;
}

float Vector2f_dot(Vector2f vector1, Vector2f vector2) {
	return vector1.x * vector2.x + vector1.y * vector2.y;
}

float Vector2f_cross(Vector2f vector1, Vector2f vector2) {
	return vector1.x * vector2.y - vector1.y * vector2.x;
}
