// ---------------------------------------------------------------------------
// 
//   Lily Engine alpha
// 
//   Copyright (c) 2010 Clifford Jolly
//     http://cliffjolly.com
//     cliff@cliffjolly.com
// 
// ---------------------------------------------------------------------------
// 
//   This program is free software; you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation; either version 2 of the License, or
//   (at your option) any later version.
//  
//   This program is distributed in the hope that it will be useful, but
//   WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//   General Public License for more details.
// 
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
//   USA
// -------------------------- END HEADER -------------------------------------

#ifndef VECTOR_H
#define VECTOR_H

#include <cmath>
#include <iostream>

class Vector3D {
	public:
		VEC_SCALAR x, y, z;
	
		Vector3D(void) {
			x = y = z = 0;
		}
		
		inline Vector3D(VEC_SCALAR x, VEC_SCALAR y, VEC_SCALAR z) {
			this->x = x;
			this->y = y;
			this->z = z;
		}
	
		inline Vector3D operator+(const Vector3D &v) const {
			Vector3D r;
			
			r.x = v.x + x;
			r.y = v.y + y;
			r.z = v.z + z;
			
			return r;
		}
		
		inline Vector3D operator-(const Vector3D &v) const {
			Vector3D r;
			
			r.x = v.x - x;
			r.y = v.y - y;
			r.z = v.z - z;
			
			return r;
		}
		
		inline Vector3D operator*(VEC_SCALAR s) const {
			Vector3D r;
			
			r.x = x * s;
			r.y = y * s;
			r.z = z * s;

			return r;
		}
		
		inline Vector3D operator/(VEC_SCALAR s) const {
			Vector3D r;
	
			r.x = x / s;
			r.y = y / s;
			r.z = z / s;

			return r;
		}
		
		inline Vector3D cross(const Vector3D &v) const {
			Vector3D r;
			
			r.x =  y   * v.z - z   *  v.y;
			r.y = -v.z * x   - v.x * -z;
			r.z =  x   * v.y - y   *  v.x;
			return r;
		}
		
		/// Dot product.
		inline VEC_SCALAR dot(const Vector3D &v) const {
			return v.x * x + v.y * y + v.z * z;
		}
		
		inline VEC_SCALAR magnitude(void) const {
			return std::sqrt(x * x + y * y + z * z);
		}
		
		// TODO: Need a ostream/istream operators and tinyXML load/save
		//   like Vector2D
};

/** @brief Stream output operator.
 * Mainly for debugging purposes, as there is no corresponding input
 * operator. Use like: cout << vector << endl;
 * @param os The ostream to output to (ie: cout, or a file).
 * @param v The vector to output.
 * */
inline std::ostream &operator<<(std::ostream &os, const Vector3D &v) {
	os << "(" << v.x << " " << v.y << " " << v.z << ")";
	return os;
}

#endif
