#ifndef Foundation_Math_Ray_INCLUDED
#define Foundation_Math_Ray_INCLUDED

#include <foundation/Math/Point.hpp>
#include <foundation/Math/Vec.hpp>

namespace Tn {

namespace math {

template <int I, typename T>
struct Ray {

    Ray(Point<I,T> const & o, Vec<I,T> const & d)
        : origin(o), direction(d) {}
    Ray() {}    // :Warning: No default initialization!

    Point<I,T> origin;
    Vec<I,T> direction;
};

template <int I, typename T>
Ray<I,T> normalize(Ray<I,T> const & ray) {
    return Ray<I,T>(ray.origin, normalize(ray.direction));
}


/* NOTE: This 'intersect' function hasn't been tested yet. Turned out
 * not to need it. Leaving it in in case it is useful in the
 * future. */

template<typename T>
Point<2,T> intersect(Ray<2,T> const & a, Ray<2,T> const & b)
{
    // See http://paulbourke.net/geometry/lineline2d/

    T x1 = a.origin[0];
    T y1 = a.origin[1];

    T x3 = b.origin[0];
    T y3 = b.origin[1];

    T n = b.direction[0] * (y1 - y3) - b.direction[1] * (x1 - x3);
    T d = b.direction[1] * a.direction[0] - b.direction[0] * a.direction[1];

    T u_a = n / d;
    return a.origin + a.direction * u_a;
}


typedef Ray<2,float> Ray2f;
typedef Ray<3,float> Ray3f;

typedef Ray<2,double> Ray2d;
typedef Ray<3,double> Ray3d;


} // namespace math

} // namespace Tn

#endif
