/*
** This file is part of the ViTE project.
**
** This software is governed by the CeCILL-A license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
** 
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
** 
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
** 
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-A license and that you accept its terms.
**
**
** ViTE developpers are (for version 0.* to 1.0):
**
**        - COULOMB Kevin
**        - FAVERGE Mathieu
**        - JAZEIX Johnny
**        - LAGRASSE Olivier
**        - MARCOUEILLE Jule
**        - NOISETTE Pascal
**        - REDONDY Arthur
**        - VUCHENER Clément 
**
*/
/*!
 *\file vbo.hpp
 */

#ifndef VBO_HPP
#define VBO_HPP


typedef double Data_type;




/*!
  \def VBO_BUFFER_OFFSET(a)
  OpenGL special macro
*/
#define VBO_BUFFER_OFFSET(a) ((char*)NULL + (a))

class Vbo;

/*!
 * \brief Manage the Vertex Buffer Object.
 */
class Vbo{

protected:

    /*!
     * \brief Number of verteces per objects.
     */
    unsigned int _nb_verteces_per_object;

    /*!
     * \brief Number of objects (container, entity...) per vbo.
     */
    unsigned int _nb_object;

    /*!
     * \brief The size of the vbo buffer: _nb_object*(number_of_vertices_per_object).
     */
    unsigned int _size;

    /*!
     * \brief Define how kind of OpenGL primitive object is made.
     *
     * Values can be : GL_LINES, GL_TRIANGLES, GL_QUADS or GL_POLYGON for example.
     */
    GLenum _object_type;

    /*!
     * \brief Define how kind of OpenGL buffer object belongs to.
     *
     * Values can be : GL_VERTEX_ARRAY or GL_COLOR_ARRAY for example.
     */
    GLenum _client_state;    


    /*!
     * \brief The vbo instance identity.
     */
    GLuint _id;

    /*!
     * \brief Define the position indicator inside the VBO buffer. Must be lesser than _size !
     */
    unsigned int _cur;

    /*!
     * \brief Define the number of vertex coordinates. Should be equal to 3.
     */
    unsigned int _nb_coordinates_per_vertex;

private:

    /*!
     * \brief The default constructor. Cannot be use for instantiation.
     */
    Vbo();

public:

    enum Type{
        TRIANGLES,
        QUADS,
        LINES
    };


    /***********************************
     *
     * Constructor and destructor.
     *
     **********************************/

   /*!
     * \brief Constructor.
     * \param nb_verteces_per_object Number of verteces per object.
     * \param nb_object Number of objects. Object can be a container or entity.
     * \param object_type Defines how kind of OpenGL primitive object is made.
     * \param client_state Define how kind of OpenGL buffer object belongs to.
     */
    Vbo(int nb_object, Type object_type);

    /*!
     * \brief The destructor.
     */
    virtual ~Vbo();



    /***********************************
     *
     * Buffer filling.
     *
     **********************************/

    /*!
     * \brief Used to inform that data have been successfully added to graphic card.
     */
    static const int VBO_OK;

    /*!
     * \brief Used to inform that the buffer is full and another VBO must be create.
     */
    static const int VBO_OUT_OF_MEMORY;

    /*!
     * \brief Used to inform that an unidentified error occurs.
     */
    static const int VBO_UNDEFINED_ERROR;

    /*!
     * \brief Fill the vertex buffer object.
     * \param data_size The vertex buffer data size.
     * \param data A vertex buffer to be display (its type MUST BE <i>Element_pos</i>).
     *
     * \return The state of the buffer.
     *
     * This function is called for each vertex, so it is an inline function. It can return several number :
     * <ul>
     * <li><b>VBO_OK</b>: data have been added to graphic card. No error.
     * <li><b>VBO_OUT_OF_MEMORY</b>: buffer is full. Another VBO must be create.
     * <li><b>VBO_UNDEFINED_ERROR</b>: an error occurs but has not been identified.
     * </ul>
     */
    int add(const unsigned int data_size, const Data_type* const data);


    /*!
     * \brief Return the remaining size of the buffer object.
     *
     * \return Number corresponding to the case number remaining.
     */
    int get_remaining_size() const;



    /***********************************
     *
     * Buffer display.
     *
     **********************************/

    /*!
     * \brief Display the VBO list inside the OpenGL area.
     */
    void display() const;



    /***********************************
     *
     * Debug tools.
     *
     **********************************/

    /*!
     * \brief Display information about VBO: its attribute values.
     */
    void display_info();


    void *operator new(size_t s){
        std::cout << "Vbo: allocation de "<< s << " octets." << std::endl;
        return malloc(s*sizeof(Vbo));
    }

};



/* Define several Vbo inherited classes */


/****************
 *
 * CONTAINER
 *
 ****************/

// struct Vbo_container : public Vbo{

// public:

//     /*!
//      * \brief The default constructor.
//      */
//     Vbo_container():Vbo(4, 8000, GL_QUADS, GL_VERTEX_ARRAY){
//     }

//     /*!
//      * \brief The destructor.
//      */
//     virtual ~Vbo_container(){
//     }

// };






/****************
 *
 * ARROW
 *
 ****************/


// /*!
//  * \brief VBO uses for triangle arrows. 
//  */
// struct Vbo_arrow_triangle : public Vbo{

// public:

//     /*!
//      * \brief The default constructor.
//      */
//     Vbo_arrow_triangle():Vbo(3, 2000, GL_TRIANGLES, GL_VERTEX_ARRAY){
//     }

//     /*!
//      * \brief The destructor.
//      */
//     virtual ~Vbo_arrow_triangle(){
//     }
// };



// /*!
//  * \brief VBO uses for line arrows. 
//  */
// struct Vbo_arrow_line : public Vbo{

// public:

//     /*!
//      * \brief The default constructor.
//      */
//     Vbo_arrow_line():Vbo(2, 8000, GL_LINES, GL_VERTEX_ARRAY){
//     }

//     /*!
//      * \brief The destructor.
//      */
//     virtual ~Vbo_arrow_line(){
//     }
// };


 #endif
