/*
** 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 developers 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 Render_alternate.hpp
 */

#ifndef RENDER_OPENGL_HPP
#define RENDER_OPENGL_HPP

class Render_alternate;
class Interface_console;
struct Container_text_;
class Vbo;

/*!
 * \brief Structure used to store arrow information.
 */
struct Arrow_{
    /*!
     * \brief Coordinates.
     */
    Element_pos start_time, end_time, start_height, end_height;
    /*!
     * \brief Colors.
     */
    Element_col red, green, blue;
};

/*!
 * \brief Structure used to store event information.
 */
struct Event_{
    /*!
     * \brief Coordinates and radius.
     */
    Element_pos time, height, container_height;
    /*!
     * \brief Colors.
     */
    Element_col red, green, blue;
};


/*!
 * \brief This class redefined the OpenGL widget - QGLWidget - to display the trace.
 */
class Render_alternate :  /*public QGLWidget,*/ public Hook_event, public Render_template
{
    Q_OBJECT
    
protected:
    
    /*!
     * \brief Contains the parent instance.
     */
    Core* _core;

    /*!
     * \brief The waiting screen display list.
     */
     GLuint _wait_list;


    /*!
     * \brief The container GLu list.
     */
    GLuint _list_containers;
    
    /*!
     * \brief The state GLu list.
     */
    GLuint _list_states;
    
     /*!
      * \brief The counter GLu list.
      */
    GLuint _list_counters;

    
    /*!
     * \brief The wait GLu list.
     */
    //  GLuint _wait_list;

    float _red, _green, _blue;
    
    std::vector<Container_text_> _texts;
    std::vector<Arrow_> _arrows;
    std::vector<Event_> _circles;


    /***********************************
     *
     * The wait screen drawing.
     *
     **********************************/

    /***********************************
     * The wait list Attributes.
     **********************************/


    /*!
     * \brief Rotation angle for the wait.
     */
    float _wait_angle;

    /*!
     * \brief Y rotation angle for the wait.
     */
    float _wait_angle_y;

    /*!
     * \brief Time in ms between two frames for the waiting screen.
     */
    static const int DRAWING_TIMER_DEFAULT;

    /*!
     * \brief Wait animation seconds per frame.
     */
    int _wait_spf;


    Vbo* _current_vbo;
    std::vector<Vbo*> _vbos;

    /*!
     * \brief Timer to animate the wait.
     */
    QTimer* _wait_timer;

public:

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

    /*!
     * \brief The default constructor
     */
    Render_alternate(Core* core, QWidget *parent, const QGLFormat& format);

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

    /*!
     * \brief Set Statistics and Informations about input trace
     */
    void set_total_width(Element_pos){}

    /*!
     * \brief Set Statistics and Informations about input trace
     */
    void set_total_time(Times){}

    /*!
     * \brief display the scale 
     */
    void display_time_scale(){}


    /***********************************
     *
     * Default QGLWidget functions.
     *
     **********************************/
     
    /*!
     * \brief Call by the system to initialize the OpenGL render area.
     */
      void initializeGL();
     
    /*!
     * \brief Call by the system when the render area was resized (occurs during a window resizement).
     * \param width : the new width of the render area.
     * \param height : the new height of the render area. 
     */
    void resizeGL(int width, int height);
     
    /*!
     * \brief Call by the system each time the render area need to be updated.
     */
    void paintGL();
    
    //void paintEvent(QPaintEvent *event);

    /* void initializeOverlayGL();
    void resizeOverlayGL(int width, int height);
    void paintOverlayGL();*/
    

    /***********************************
     *
     * Building functions.
     *
     **********************************/

    /*!
     * \brief This function constructs the trace.
     */
    //  bool display_build() ;

    /*!
     * \brief This function releases the trace.
     */
    //   bool display_unbuild() ;

    /*!
     * \brief Proceeds with the initialization of the OpenGL draw functions.
     */
    void start_draw();

    /*!
     * \brief Creates and opens the display list for container draws.
     */
    void start_draw_containers();

    /*!
     * \brief Draw a container according to the parameters
     * \param x the x position of the container
     * \param y the y position of the container
     * \param w the width of the container
     * \param h the height of the container
     */
    void draw_container(const Element_pos x, const Element_pos y, const Element_pos w, const Element_pos h);

    /*!
     * \brief Draw the text of a container.
     * \param x the x position of the text.
     * \param y the y position of the text.
     * \param value the string value of the text.
     *
     * This function stores text in a list. This list will be display each time the render area need to be updated.
     */
    void draw_container_text(const Element_pos x, const Element_pos y, const std::string value);

    /*!
     * \brief Closes the container display list.
     */
    void end_draw_containers();
     
    /*!
     * \brief Creates and opens the display list for stater draws.
     */
    void start_draw_states();

    /*!
     * \brief Draw a state of the trace.
     * \param start the beginning time of the state.
     * \param end the ending time of the state.
     * \param base vertical position of the state.
     * \param height the state height.
     * \param r the red color rate of the state.
     * \param g the green color rate of the state.
     * \param b the blue color rate of the state.
     */
    void draw_state(const Element_pos start , const Element_pos end, const Element_pos base, const Element_pos height, const Element_col r, const Element_col g, const Element_col b);

    /*!
     * \brief Closes the state display list.
     */
    void end_draw_states();

    /*!
     * \brief Open the arrow display list.
     */
    void start_draw_arrows();

    /*!
     * \brief Draw an arrow.
     * \param start_time the beginning time of the arrow.
     * \param end_time the ending time of the arrow.
     * \param start_height vertical position of the begining time of the arrow.
     * \param end_height vertical position of the ending time of the arrow.
     *
     * This function stores all the information of the arrow to display it each time the render area need to be updated.
     */
    void draw_arrow(const Element_pos start_time, const Element_pos end_time, const Element_pos start_height, const Element_pos end_height,const Element_col red, const Element_col green, const Element_col blue);

    /*!
     * \brief Closes the arrow display list.
     */
    void end_draw_arrows();

    /*!
     * \brief Draw arrows contained in the Arrow_ vector
     * \param arrows An arrow vector.
     */
    // void draw_stored_arrows(std::vector<Arrow_> &arrows);

    void start_draw_events();

    /*!
     * \brief Draw an event.
     * \param time time when the event occurs.
     * \param height vertical position of the event.
     * \param container_height information to draw event. It corresponds to the container height when they are drawn horizontally.
     *
     *
     * \brief Creates and opens the display list for container draws.
     *
     * This function stores all the information of the event to display it each time the render area need to be updated.
     */
    void draw_event(const Element_pos time, const Element_pos height,  const Element_pos container_height);

    void end_draw_events();


    /*!
     * \brief Draw events contained in the Event_ vector
     * \param events An event vector.
     */
    //  void draw_stored_events(std::vector<Event_> &events);

    /*!
     * \brief Creates and opens the display list for counter draws.
     */
    void start_draw_counter();
     
    /*!
     * \brief Draw a point of the counter.
     * \param x x position of the point.
     * \param y y position of the point.
     *
     * Each time counter is increased, this function is called with the coordinates of the new point.
     */
    void draw_counter(const Element_pos x, const Element_pos y);
     
    /*!
     * \brief Closes the counter display list.
     */
    void end_draw_counter();

    /*!
     * \brief Called before ruler drawing.
     */
    void start_ruler();
     
    /*!
     * \brief Called after ruler drawing.
     */
    void end_ruler();
     

    /*!
     * \brief Do nothing (it is present for compatibility of the Render class).
     */
    void end_draw();

    

    /***********************************
     *
     * Render OpenGL drawing functions.
     *
     **********************************/

    /*!
     * \brief Display a wait on the screen if there is no file opened.
     * \return Asset value of the wait.
     */
    GLuint draw_wait();

    /*!
     * \brief Draw the ruler display list.
     */
    void call_ruler();



    /***********************************
     *
     * Building functions.
     *
     **********************************/

    /*!
     * \brief This function draws the trace.
     */
    bool build();

    /*!
     * \brief This function releases the trace.
     */
    bool unbuild();

    /***********************************
     *
     * Displaying functions.
     *
     **********************************/

 //    /*!
//      * \brief Display on screen containers between container_begin and container_end.
//      * \param container_begin integer value : id of the first container.
//      * \param container_end integer value : id of the last container.
//      */
//       void display_container(Element_count container_begin, Element_count container_end) =0;

//     /*!
//      * \brief Display on screen states between timer_begin and time_end, 
//      * container_begin and container_end and with timer width between depth_begin and depth_end.
//      * \param time_begin floating point value : time of the first state.
//      * \param time_end floating point value : time of the last state.
//      * \param container_begin integer value : id of the first container.
//      * \param container_end integer value : id of the last container.
//      * \param depth_begin floating point value : width of the narrowest state.
//      * \param depth_end floating point value : width of the widest state.
//      */
//        void display_state(Element_pos time_begin, Element_pos time_end, 
//                        Element_count container_begin, Element_count container_end, 
//                        Element_pos depth_begin, Element_pos depth_end) =0;

//     /*!
//      * \brief Display on screen arrows between timer_begin and time_end, 
//      * container_begin and container_end and with timer width between depth_begin and depth_end.
//      * \param time_begin floating point value : time of the smallest arrow time value.
//      * \param time_end floating point value : time of the higher arrow time value.
//      * \param container_begin integer value : id of the first container.
//      * \param container_end integer value : id of the last container.
//      * \param depth_begin floating point value : the narrowest difference between 
//      * the beginning time and the ending time of the arrow.
//      * \param depth_end floating point value : width of the widest difference between
//      * the beginning time and the ending time of the arrow.
//      */
//     virtual void display_arrow(Element_pos time_begin, Element_pos time_end, 
//                        Element_count container_begin, Element_count container_end, 
//                        Element_pos depth_begin, Element_pos depth_end) =0;

//     /*!
//      * \brief Display on screen events between timer_begin and time_end, 
//      * container_begin and container_end.
//      * \param time_begin floating point value : time of the first event.
//      * \param time_end floating point value : time of the last event.
//      * \param container_begin integer value : id of the first container.
//      * \param container_end integer value : id of the last container.
//      */
//     virtual void display_event(Element_pos time_begin, Element_pos time_end, 
//                        Element_count container_begin, Element_count container_end) =0;  

//     /*!
//      * \brief Display on screen counters between timer_begin and time_end, 
//      * container_begin and container_end.
//      * \param time_begin floating point value : time of the smallest counter time value.
//      * \param time_end floating point value : time of the higher counter time value.
//      * \param container_begin integer value : id of the first container.
//      * \param container_end integer value : id of the last container.
//      */
//     virtual void display_counter(Element_pos time_begin, Element_pos time_end, 
//                          Element_count container_begin, Element_count container_end) =0;   
    
    /*!
     * \brief Set the color for the further drawings.
     * \param r the red value. Within [0 ; 1].
     * \param g the green value. Within [0 ; 1].
     * \param b the blue value. Within [0 ; 1].   
     */
    void set_color(float r, float g, float b);

    /*!
     * \brief Draw a text.
     * \param x the horizontal position of the left bottom corner of the text.
     * \param y the vertical position of the left bottom corner of the text.
     * \param z the deep position of the text.
     * \param s the text.
     */
    virtual void draw_text(const Element_pos x, const Element_pos y, const Element_pos z, const std::string s);

    /*!
     * \brief Draw a quad.
     * \param x the horizontal position of the left bottom corner of the quad.
     * \param y the vertical position of the left bottom corner of the quad.
     * \param z the deep position of the quad.
     * \param w the width of the quad.
     * \param h the height of the quad.
     */
    void draw_quad(Element_pos x, Element_pos y, Element_pos z, Element_pos w, Element_pos h);

    /*!
     * \brief Draw a triangle.
     * \param x the horizontal position of the triangle center.
     * \param y the vertical position of the triangle center.
     * \param size the edge size.
     * \param r the rotation of triangle. (clockwise and in degree)
     */
    void draw_triangle(Element_pos x, Element_pos y,
                       Element_pos size, Element_pos r);
    
    /*!
     * \brief Draw a line.
     * \param x1 the horizontal position of the first point.
     * \param y1 the vertical position of the firt point.
     * \param x2 the horizontal position of the second point.
     * \param y2 the vertical position of the second point.
     * \param z the deep position of the triangle.
     */
    void draw_line(Element_pos x1, Element_pos y1, Element_pos x2, Element_pos y2, Element_pos z);

    /*!
     * \brief Draw a circle.
     * \param x the horizontal position of the circle center.
     * \param y the vertical position of the circle center.
     * \param z the deep position of the circle.
     * \param r the circle radius.
     */
    void draw_circle(Element_pos x, Element_pos y, Element_pos z, Element_pos r);

    /* Temporary methods. Use to draw stored arrows and circles. It is to prevent scaling */
    void draw_stored_arrows();
    void draw_stored_circles();

    void draw_stored_texts();
};



#endif
