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


#ifndef HOOK_EVENT_HPP
#define HOOK_EVENT_HPP

class Core;
class Render;

/*!
 * \brief Structure used to store selection coordinate information.
 */
struct Selection_{
    /*!
     * \brief x scale.
     */
    Element_pos x_scale;

    /*!
     * \brief y scale.
     */
    Element_pos y_scale;

    /*!
     * \brief x translation.
     */
    Element_pos x_translate;

    /*!
     * \brief y translation.
     */
    Element_pos y_translate;
};


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

protected:


    /*!
     * \brief Contains container text coordinates.
     */
    std::list<Element_pos> _text_pos;

    /*!
     * \brief Contains container strings.
     */
    std::list<std::string> _text_value;

    /*!
     * \brief Contains the previous selection coordinates.
     */
    std::stack<Selection_> _previous_selection;

    /*!
     * \brief Contains the OpenGL render instance.
     */
    Render* _render_instance;


    /*!
     * \brief Contains the parent instance.
     */
    Core* _core;

    /*!
     * \brief timer to check whether we launched a double click event or a single click event
     */
    QTimer* _timer;

    /*!
     * \briefcheck if the timer has already been launched and the signal connected to the slot
     */
    bool _connected;


    /***********************************
     *
     * Render area state attributes.
     *
     **********************************/

    /*!
     * \brief State when there is no file opened.
     */
    static const int DRAWING_STATE_WAITING;

    /*!
     * \brief State when the application is drawing traces.
     */
    static const int DRAWING_STATE_DRAWING;


    /*!
     * \brief Contains the kind of state for the render area (drawing, waiting, etc.).
     */
    int _state;

    /*!
     * \brief Indicated if mouse is pressed or not.
     */
    bool _mouse_pressed;

    /*!
     * \brief Indicated if mouse is pressed inside the container area.
     */
    bool _mouse_pressed_inside_container;

    /*!
     * \brief Indicated if mouse is pressed inside the ruler area.
     */
    bool _mouse_pressed_inside_ruler;

    /*!
     * \brief Used to store the mouse last x position.
     */
    int _mouse_x;

    /*!
     * \brief Used to store the mouse last y position.
     */
    int _mouse_y;

    /*!
     * \brief Used to store the mouse current x position.
     */
    int _new_mouse_x;

    /*!
     * \brief Used to store the mouse current y position.
     */
    int _new_mouse_y;

    /*!
     * \brief Indicate if the scroll was asked by key capture in openGL render area.
     */
    bool _key_scrolling;

    /*!
     * \brief Alpha color of the selection rectangle.
     */
    double _selection_rectangle_alpha;

    /*!
     * \brief Define the minimum width and height to draw the selection rectangle (avoid bas manipulations).
     */
    Element_pos _minimum_distance_for_selection;

    /*!
     * \brief Define the scrolling factor when CTRL key is pressed.
     */
    static const int _ctrl_scroll_factor;

    /*!
     * \brief Define the scrolling factor when CTRL key is pressed.
     */
    static const int _ctrl_zoom_factor;

    /***********************************
     *
     * Default QWidget functions.
     *
     **********************************/

    /*!
     * \brief This functions receives all mouse press events.
     * \param event The event triggered by mouse.
     */
    void mousePressEvent(QMouseEvent * event) override;

    /*!
     * \brief This functions receives all mouse double click events.
     * \param event The event triggered by mouse.
     */
    void mouseDoubleClickEvent(QMouseEvent * event) override;

    /*!
     * \brief If user press, this functions receives all mouse move events until user release mouse.
     * \param event The event triggered by mouse.
     */
    void mouseMoveEvent(QMouseEvent * event) override;

    /*!
     * \brief This functions receives all mouse release events.
     * \param event The event triggered by mouse.
     */
    void mouseReleaseEvent(QMouseEvent * event) override;

    /*!
     * \brief This functions receives all mouse wheel events.
     * \param event The event triggered by the mouse wheel.
     */
    void wheelEvent(QWheelEvent * event) override;

    /*!
     * \brief This functions receives all keyboard events.
     * \param event The event triggered by the keyboard event.
     */
    void keyPressEvent(QKeyEvent * event) override;

    /*!
     * \brief This functions receives all keyboard release events.
     * \param event The event triggered by a keyboard release.
     */
    void keyReleaseEvent(QKeyEvent * event) override;

    /*!
     * Use to update the render area.
     */
    void updateRender();


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

    /*!
     * \brief The default constructor.
     *
     * Default constructor has a private scope to avoid any direct instantiation of Hook_event.
     */
    Hook_event();


public:


    /*!
     * \brief The constructor.
     * \param render_instance The instance of a drawing class.
     */
    Hook_event(Render* render_instance, Core* core, QWidget *parent, const QGLFormat& format);

    /*!
     * \brief The destructor
     */
    ~Hook_event() override;



    /***********************************
     *
     * Scaling and scrolling functions.
     *
     **********************************/


    /*!
     * \brief Change the scale of state drawing.
     * \param scale_coeff The new coefficient scale value to add to the current scale.
     */
    void change_scale(Element_pos scale_coeff);

    /*!
     * \brief Change the scale of the y state drawing.
     * \param scale_coeff The new coefficient scale value to add to the current scale.
     */
    void change_scale_y(Element_pos scale_coeff);

    /*!
     * \brief Replace the current scale by a new scale. (horizontally)
     * \param new_scale The new scale value to replace the current scale.
     */
    void replace_scale(Element_pos new_scale);

    /*!
     * \brief Replace the current scale by a new scale. (vertically)
     * \param new_scale The new scale value to replace the current scale.
     */
    void replace_scale_y(Element_pos new_scale);

    /*!
     * \brief Change the x position of camera view for state drawing area.
     * \param translate The new position.
     */
    void change_translate(int translate);/* temporary -> to change the translate to view states */

    /*!
     * \brief Change the y position of camera view for state drawing area.
     * \param translate The new position.
     */
    void change_translate_y(int translate);/* temporary -> to change the translate to view states */

    /*!
     * \brief Replace the current x translate by a new translate.
     * \param new_translate The new translate value to replace the current translate.
     */
    void replace_translate(Element_pos new_translate);

    /*!
     * \brief Replace the current y translate by a new translate.
     * \param new_translate The new translate value to replace the current translate.
     */
    void replace_translate_y(Element_pos new_translate);

    /*!
     * \brief Pre registered translation values (for x or y translate).
     * \param id The pre registered translation id.
     */
    void registered_translate(int id);

    /*!
     * \brief Refresh scroll bar positions when shortcuts execute movements
     * \param LENGTH_CHANGED If true the total length of the scroll bar will be updated.
     */
    void refresh_scroll_bars(bool LENGTH_CHANGED = false);

    /*!
     * \brief Change the percentage taken by container display in the render area.
     * \param view_size The new percentage (between 0 to 100).
     */
    void change_scale_container_state(int view_size);/* temporary -> to change the size of container view */

    /*!
     * \brief Scale the current view to the zoom box shape.
     * \param x_min the x minimum position.
     * \param x_max the x maximum position.
     * \param y_min the y minimum position.
     * \param y_max the y maximum position.
     */
    void apply_zoom_box(Element_pos x_min, Element_pos x_max, Element_pos y_min, Element_pos y_max);

    void apply_zoom_on_interval(Element_pos t1, Element_pos t2);
};



#endif
