#pragma once

#include "point3d.h"
#include "rotation.h"

class Motion;

class Origin
{
#if defined(USE_SIGNATURE)
	friend int Is_Signature_Bad(const volatile Origin *);
#endif

public:
	Point3D linearPosition;
	Quaternion angularPosition;

	static const Origin Identity;

	Origin()	{}
	Origin(const Point3D &t, const EulerAngles& q)
	{
		Check(&t);
		Check(&q);
		linearPosition = t;
		angularPosition = q;
	}
	Origin(const Point3D &t, const Quaternion& q)
	{
		Check(&t);
		Check(&q);
		linearPosition = t;
		angularPosition = q;
	}
	Origin(const LinearMatrix &matrix);

	Origin& operator=(const Origin& p);
	Origin& operator=(const Point3D& p)
	{
		Check_Pointer(this);
		Check(&p);
		linearPosition = p;
		return *this;
	}
	Origin& operator=(const EulerAngles& q)
	{
		Check_Pointer(this);
		Check(&q);
		angularPosition = q;
		return *this;
	}
	Origin& operator=(const YawPitchRoll& q)
	{
		Check_Pointer(this);
		Check(&q);
		angularPosition = q;
		return *this;
	}
	Origin& operator=(const Quaternion& q)
	{
		Check_Pointer(this);
		Check(&q);
		angularPosition = q;
		return *this;
	}
	Origin& operator=(const LinearMatrix &m);

	Logical operator==(const Origin&) const;

	Origin& AddScaled(const Origin& source, const Motion& delta, Scalar t);
	Origin& Lerp(const Origin& start, const Origin& end, Scalar t);

	friend std::ostream& operator<<(std::ostream& stream, const Origin& p);
	Logical TestInstance() const;
	static Logical TestClass();
};

inline Point3D& Point3D::operator=(const Origin& p)			{ return operator=(p.linearPosition); }
inline EulerAngles& EulerAngles::operator=(const Origin& p)	{ return operator=(p.angularPosition); }
inline Quaternion& Quaternion::operator=(const Origin& p)	{ return operator=(p.angularPosition); }
