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

#ifndef RENDER_OPENGL_HPP
#define RENDER_OPENGL_HPP

#include <stack>
#include <cmath>
#include <sstream>
/* -- */
#include <QObject>
#include <QGLWidget>
#include <QLabel>
#include <QPainter>
/* -- */
#include "common/common.hpp"
#include "common/Info.hpp"
/* -- */
#include "render/Geometry.hpp"
#include "render/Hook_event.hpp"
#include "render/Render.hpp"
#include "render/Minimap.hpp"
#include "render/Ruler.hpp"
#include "render/GanttDiagram.hpp"

/*!
 * \brief This class redefined the OpenGL widget - QGLWidget - to display the trace.
 */
class Render_opengl :  /*public QGLWidget,*/ public Hook_event, public Render
{
    Q_OBJECT

private:

    bool _draw_container;
    bool _draw_state;
    bool _draw_ruler;
    bool _draw_arrow;
    bool _draw_event;

protected:

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

    /*!
     * \brief The minimap.
     */
    Minimap _minimap;

    /*!
     * \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 arrows GLu list.
     */
    GLuint _list_arrows;

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

    float _red, _green, _blue;

    std::vector<Container_text_> _texts;
    std::map<long int, Variable_text_> _variable_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 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;

    /*!
     * \brief Offset of the vertical helper line
     */
    Element_pos vertical_line;


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

    /*!
     * \brief QLabel to display minimap.
     */
    //  QLabel* _minimap_widget;

    /*!
     * \brief QImage to store the trace thumbnail.
     */
    // QImage* _minimap_image;

    /*!
     * \brief Create a minimap from the current render.
     * \param width The desired width for the image.
     * \param height The desired height for the image.
     */
    // void create_minimap(const int width, const int height);

    /*!
     * \brief Update the minimap according to the current viewport.
     */
    //   void update_minimap();

    /*!
     * \brief Release data for minimap.
     */
    //  void release_minimap();

public:

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

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

    /*!
     * \brief The destructor (~Render_opengl will never be called, so use another method to release memory)
     */
    void release();

    /**
     * Functions inherited from Render.hpp
     */
    void start_draw() override;
    void end_draw() override;

    void start_draw_containers() override;
    void end_draw_containers() override;

    void start_draw_states() override;
    void draw_state(const Element_pos,
                    const Element_pos,
                    const Element_pos,
                    const Element_pos,
                    const Element_pos,
                          EntityValue*) override;
    void end_draw_states() override;

    void start_draw_arrows() override;
    void draw_arrow(const Element_pos,
                    const Element_pos,
                    const Element_pos,
                    const Element_pos,
                    const Element_col,
                    const Element_col,
                    const Element_col,
                         EntityValue*) override;
    void end_draw_arrows() override;

    void start_draw_counter() override;
    void end_draw_counter() override;

    void start_draw_events() override;
    void draw_event(const Element_pos,
                    const Element_pos,
                    const Element_pos,
                    EntityValue *) override;
    void end_draw_events() override;

    void start_ruler() override;
    void end_ruler() override;

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

    void set_color(float r, float g, float b) override;
    void draw_text(const Element_pos x,
                   const Element_pos y,
                   const Element_pos z,
                   const std::string s) override;
    void draw_text_value(long int id,
                         double text,
                         double y) override;
    void draw_quad(Element_pos x,
                   Element_pos y,
                   Element_pos z,
                   Element_pos w,
                   Element_pos h) override;
    void draw_triangle(Element_pos x,
                       Element_pos y,
                       Element_pos size,
                       Element_pos r) override;
    void draw_line(Element_pos x1,
                   Element_pos y1,
                   Element_pos x2,
                   Element_pos y2,
                   Element_pos z) override;
    void draw_circle(Element_pos x,
                     Element_pos y,
                     Element_pos z,
                     Element_pos r) override;

    void set_vertical_line(Element_pos l) override;
    void draw_vertical_line() override;

    void call_ruler() override;

    /***********************************
     *
     * Default QGLWidget functions.
     *
     **********************************/

    /*!
     * \brief Call by the system to initialize the OpenGL render area.
     */
    void initializeGL() override;

    /*!
     * \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) override;

    /*!
     * \brief Call by the system each time the render area need to be updated.
     */
    void paintGL() override;

    //void paintEvent(QPaintEvent *event);

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

    /*!
     * \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 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);

    template <int N> void cos_table_builder(double table[]);
    template <int N> void sin_table_builder(double table[]);



    /***********************************
     *
     * 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();

    /* 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();

    /*!
     * \brief Show the minimap.
     */
    void show_minimap();

    /*! Function that only delete the arrows of the screen */
    void clear_arrow ();
    /*! Function that only delete the text of the screen */
    void clear_text ();


    /*!
     * \brief returns the offset of the vertical helper line
     */
    Element_pos get_vertical_line();

    /**
     * Building functions.
     */

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

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

    /**
     * Functions specifics to OpenGL render.
     */

    /*!
     * \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(){}

    //    void set_vertical_line(int l){}
    //  void draw_vertical_line();

public slots:
    /*!
     * \brief slot connected to the simple click event
     */
    void update_vertical_line() override;
};

#endif
