// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, 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.
//
// Eigen 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 Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#ifndef EIGEN_GPUHELPER_H
#define EIGEN_GPUHELPER_H

#include <Eigen/Geometry>
#include <GL/gl.h>
#include <vector>

using namespace Eigen;

typedef Vector4f Color;

class GpuHelper
{
  public:

    GpuHelper();

    ~GpuHelper();

    enum ProjectionMode2D { PM_Normalized = 1, PM_Viewport = 2 };
    void pushProjectionMode2D(ProjectionMode2D pm);
    void popProjectionMode2D();

    /** Multiply the OpenGL matrix \a matrixTarget by the matrix \a mat.
        Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
        and does a proper call to the right glMultMatrix*() function according to the scalar type
        and storage order.
        \warning glMatrixMode() must never be called directly. If your're unsure, use forceMatrixMode().
        \sa Matrix, loadMatrix(), forceMatrixMode()
    */
    template<typename Scalar, int _Flags>
    void multMatrix(const Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget);

    /** Load the matrix \a mat to the OpenGL matrix \a matrixTarget.
        Essentially, this helper function automatically calls glMatrixMode(matrixTarget) if required
        and does a proper call to the right glLoadMatrix*() or glLoadIdentity() function according to the scalar type
        and storage order.
        \warning glMatrixMode() must never be called directly. If your're unsure, use forceMatrixMode().
        \sa Matrix, multMatrix(), forceMatrixMode()
    */
    template<typename Scalar, int _Flags>
    void loadMatrix(const Eigen::Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget);

    template<typename Scalar, typename Derived>
    void loadMatrix(
        const Eigen::CwiseNullaryOp<Eigen::ei_scalar_identity_op<Scalar>,Derived>&,
        GLenum matrixTarget);

    /** Make the matrix \a matrixTarget the current OpenGL matrix target.
        Call this function before loadMatrix() or multMatrix() if you cannot guarantee that glMatrixMode()
        has never been called after the last loadMatrix() or multMatrix() calls.
        \todo provides a debug mode checking the sanity of the cached matrix mode.
    */
    inline void forceMatrixTarget(GLenum matrixTarget) {glMatrixMode(mCurrentMatrixTarget=matrixTarget);}

    inline void setMatrixTarget(GLenum matrixTarget);

    /** Push the OpenGL matrix \a matrixTarget and load \a mat.
    */
    template<typename Scalar, int _Flags>
    inline void pushMatrix(const Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget);

    template<typename Scalar, typename Derived>
    void pushMatrix(
        const Eigen::CwiseNullaryOp<Eigen::ei_scalar_identity_op<Scalar>,Derived>&,
        GLenum matrixTarget);

    /** Push and clone the OpenGL matrix \a matrixTarget
    */
    inline void pushMatrix(GLenum matrixTarget);

    /** Pop the OpenGL matrix \a matrixTarget
    */
    inline void popMatrix(GLenum matrixTarget);

    void drawVector(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
    void drawVectorBox(const Vector3f& position, const Vector3f& vec, const Color& color, float aspect = 50.);
    void drawUnitCube(void);
    void drawUnitSphere(int level=0);

    /// draw the \a nofElement first elements
    inline void draw(GLenum mode, uint nofElement);

    /// draw a range of elements
    inline void draw(GLenum mode, uint start, uint end);

    /// draw an indexed subset
    inline void draw(GLenum mode, const std::vector<uint>* pIndexes);

protected:

    void update(void);

    GLuint mColorBufferId;
    int mVpWidth, mVpHeight;
    GLenum mCurrentMatrixTarget;
    bool mInitialized;
};

/** Singleton shortcut
*/
extern GpuHelper gpu;


/** \internal
*/
template<bool RowMajor, int _Flags> struct GlMatrixHelper;

template<int _Flags> struct GlMatrixHelper<false,_Flags>
{
    static void loadMatrix(const Matrix<float, 4,4, _Flags, 4,4>&  mat) { glLoadMatrixf(mat.data()); }
    static void loadMatrix(const Matrix<double,4,4, _Flags, 4,4>& mat) { glLoadMatrixd(mat.data()); }
    static void multMatrix(const Matrix<float, 4,4, _Flags, 4,4>&  mat) { glMultMatrixf(mat.data()); }
    static void multMatrix(const Matrix<double,4,4, _Flags, 4,4>& mat) { glMultMatrixd(mat.data()); }
};

template<int _Flags> struct GlMatrixHelper<true,_Flags>
{
    static void loadMatrix(const Matrix<float, 4,4, _Flags, 4,4>&  mat) { glLoadMatrixf(mat.transpose().eval().data()); }
    static void loadMatrix(const Matrix<double,4,4, _Flags, 4,4>& mat) { glLoadMatrixd(mat.transpose().eval().data()); }
    static void multMatrix(const Matrix<float, 4,4, _Flags, 4,4>&  mat) { glMultMatrixf(mat.transpose().eval().data()); }
    static void multMatrix(const Matrix<double,4,4, _Flags, 4,4>& mat) { glMultMatrixd(mat.transpose().eval().data()); }
};

inline void GpuHelper::setMatrixTarget(GLenum matrixTarget)
{
    if (matrixTarget != mCurrentMatrixTarget)
        glMatrixMode(mCurrentMatrixTarget=matrixTarget);
}

template<typename Scalar, int _Flags>
void GpuHelper::multMatrix(const Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget)
{
    setMatrixTarget(matrixTarget);
    GlMatrixHelper<_Flags&Eigen::RowMajorBit, _Flags>::multMatrix(mat);
}

template<typename Scalar, typename Derived>
void GpuHelper::loadMatrix(
    const Eigen::CwiseNullaryOp<Eigen::ei_scalar_identity_op<Scalar>,Derived>&,
    GLenum matrixTarget)
{
    setMatrixTarget(matrixTarget);
    glLoadIdentity();
}

template<typename Scalar, int _Flags>
void GpuHelper::loadMatrix(const Eigen::Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget)
{
    setMatrixTarget(matrixTarget);
    GlMatrixHelper<(_Flags&Eigen::RowMajorBit)!=0, _Flags>::loadMatrix(mat);
}

inline void GpuHelper::pushMatrix(GLenum matrixTarget)
{
    setMatrixTarget(matrixTarget);
    glPushMatrix();
}

template<typename Scalar, int _Flags>
inline void GpuHelper::pushMatrix(const Matrix<Scalar,4,4, _Flags, 4,4>& mat, GLenum matrixTarget)
{
    pushMatrix(matrixTarget);
    GlMatrixHelper<_Flags&Eigen::RowMajorBit,_Flags>::loadMatrix(mat);
}

template<typename Scalar, typename Derived>
void GpuHelper::pushMatrix(
    const Eigen::CwiseNullaryOp<Eigen::ei_scalar_identity_op<Scalar>,Derived>&,
    GLenum matrixTarget)
{
    pushMatrix(matrixTarget);
    glLoadIdentity();
}

inline void GpuHelper::popMatrix(GLenum matrixTarget)
{
    setMatrixTarget(matrixTarget);
    glPopMatrix();
}

inline void GpuHelper::draw(GLenum mode, uint nofElement)
{
    glDrawArrays(mode, 0, nofElement);
}


inline void GpuHelper::draw(GLenum mode, const std::vector<uint>* pIndexes)
{
    glDrawElements(mode, pIndexes->size(), GL_UNSIGNED_INT, &(pIndexes->front()));
}

inline void GpuHelper::draw(GLenum mode, uint start, uint end)
{
    glDrawArrays(mode, start, end-start);
}

#endif // EIGEN_GPUHELPER_H
