#pragma once
#ifndef INERTIA_QUATERNION_H
#define INERTIA_QUATERNION_H

namespace inertia
{
	/** @brief Quaternion
	 *
	 *  A Simple quaternion container.
	 */
	struct INERTIA_API Quaternion
	{
		double w; ///< First quaternion component.
		double x; ///< Second quaternion component.
		double y; ///< Third quaternion component.
		double z; ///< Fourth quaternion component.

		/** Default constructor.
		 *  Creates a quaternion with values [1,0,0,0].
		 */
		Quaternion();

		/** Constructor with quaternion components.
		 *  @param w the first component
		 *  @param x the second component
		 *  @param y the third component
		 *  @param z the fourth component
		 */
		Quaternion(double const& w, double const& x, double const& y, double const& z);

		/** Returns 3 Euler angles. default in ZYX order.
		 *  @param order the rotation order
		 *  @return the vector with 3 Euler angles
		 */
		std::vector<double> toEulerAngles(std::wstring const& order = L"ZYX") const;


		/** Normalize the given quaternion.
		 *  @param q the quaternion to normalize
		 *  @return the normalized quaternion
		 */
		static Quaternion normalize(Quaternion const& q);

		/** Inverse the given (normalzized) quaternion.
		 *  @param q the quaternion to inverse
		 *  @return the inversed quaternion
		 */
		static Quaternion inverse(Quaternion const& q);

		/** Multiply the given (normalzized) quaternions (r=pq).
		 *  @param p the first quaternion to multiply
		 *  @param q the second quaternion to multiply
		 *  @return the multiplied quaternion
		 */
		static Quaternion multiply(Quaternion const& p, Quaternion const& q);

		/** Return the average (slerp) of the given quaternions. NOTE: not verified.
		 *  @param qs the vector of quaternions to average
		 *  @return the averaged quaternion
		 */
		static Quaternion average(std::vector<Quaternion> const& qs);
	};
}

#endif // INERTIA_QUATERNION_H
