// ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
// vec2.c
//
// @note A simple demo of Object Oriented C, using struct vec2 as an object example.
// @author Jorma Rebane
// @date 15.11.2013
//
// ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#include <stdio.h>	// printf, sprintf
#include <stdlib.h>	// system
#include <math.h>	// sqrtf


#if _MSC_VER // VC++ defines snprintf as sprintf_s
	#define snprintf sprintf_s // so lets fix that.
#endif


// Typical 2D vector for any graphics program
typedef struct
{
	float x;
	float y;
} vec2;


/**
 * @brief Creates a new [vec2] { x, y }
 * @note We return by VALUE, because [vec2] is only 8 bytes
 */
vec2 vec2_new(float x, float y)
{
	vec2 a = { x, y };
	return a;
}


/**
 * @return Length of the specified 2D vector.
 * @note Pass [vec2] by value
 */
float vec2_length(vec2 o)
{
	// sqrt(x*x + y*y)
	return sqrtf( (o.x*o.x) + (o.y*o.y) );
}


/**
 * @brief Add a+b -> new vec2
 *			c = a + b
 * @note Both args passed by value
 */
vec2 vec2_add(vec2 a, vec2 b)
{
	vec2 c = { a.x + b.x, a.y + b.y };
	return c;
}


/**
 * @brief Returns a volatile string that represents this object
 * @note The string will be overwritten on next call of the function
 */
const char* vec2_toString(vec2 o)
{
	static char stringbuff[64];		// a static [.bss seg] string buffer
	snprintf(stringbuff, sizeof(stringbuff), "{ %+.3f, %+.3f }", o.x, o.y);
	return stringbuff;
}


int main(int argc, char** argv)
{
	// we could do multiple inits in C'11, but not in C'99
	//vec2 a = { 0.2f, +0.4f };	
	//vec2 b = { 0.7f, -0.1f };	

	vec2 a, b, c, d;
	a = vec2_new(0.2f, 0.4f);
	b = vec2_new(0.7f, -0.1f);
	c = vec2_new(0.5f, 0.75f);

	// d = (a+b) + c
	d = vec2_add(vec2_add(a, b), c);

	printf("a = %s\n", vec2_toString(a));
	printf("b = %s\n", vec2_toString(b));
	printf("c = %s\n", vec2_toString(c));
	printf("d = %s\n", vec2_toString(d));
	printf("a.length = %.3f\n", vec2_length(a));
	printf("b.length = %.3f\n", vec2_length(b));
	printf("c.length = %.3f\n", vec2_length(c));
	printf("d.length = %.3f\n", vec2_length(d));

	system("pause");
	return 0;
}