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

#ifndef DRAW_STATS_HPP
#define DRAW_STATS_HPP

/*!
 * \def _HEIGHT_FOR_ONE_CONTAINER_DEFAULT
 * \brief The default height for one container's statistics.
 */
#define _HEIGHT_FOR_ONE_CONTAINER_DEFAULT 450.0f

/*!
 * \def _POS_X_CONTAINER_NAME
 * \brief The default x position for the container name.
 *        The origin is set at the north west.
 */
#define _POS_X_CONTAINER_NAME 10.0f

/*!
 * \def _POS_Y_CONTAINER_NAME
 * \brief The default y position for the container name.
 *        The origin is set at the north west.
 */
#define _POS_Y_CONTAINER_NAME _HEIGHT_FOR_ONE_CONTAINER_DEFAULT-50.0f

/*!
 * \def _WIDTH_HISTOGRAM_DEFAULT
 * \brief The default width for a container in histogram mode.
 */
#define _WIDTH_HISTOGRAM_DEFAULT 30.f

/*!
 * \def _START_HISTOGRAM_X_DEFAULT
 * \brief The default x position for origin in histogram mode.
 */
#define _START_HISTOGRAM_X_DEFAULT 80.f

/*!
 * \def _START_HISTOGRAM_Y_DEFAULT
 * \brief The default Y position for origin in histogram mode.
 */
#define _START_HISTOGRAM_Y_DEFAULT _HEIGHT_FOR_ONE_CONTAINER_DEFAULT/2.

/*!
 * \def _POS_X_LEGEND_DEFAULT
 * \brief The default position for the legend.
 */
#define _POS_X_LEGEND_DEFAULT 10.f

/*!
 * \def _POS_Y_LEGEND_DEFAULT
 * \brief The default position for the legend.
 */
#define _POS_Y_LEGEND_DEFAULT 60.f


/*!
 * \class DrawStats
 * \brief Browse the stats and call back T drawing methods
 */
template<class T>
class DrawStats {
    
protected:
    
    /*!
     * \brief The containers which we want the statistics
     */
    std::vector<Container *> _containers_to_print;

    /*!
     * \brief The states and their statistics
     */
    std::vector<std::map<const EntityValue*, stats*> > _states;

    // Interval to compute statistics
    double _start_time;
    double _end_time;
    /*!
     * \brief unused for the moment.
     * Can be useful to keep the previous stats and so do not compute them one more time, if the interval [_prev_start, _prev_end] belongs to [_new_start, _new_end]
     */
    double _previous_start_time;
    /*!
     * \brief unused for the moment.
     */
    double _previous_end_time;

    // Geometrical informations about the stats shape.
    double _size_for_one_container;
    double _pos_x_container_name;
    double _pos_y_container_name;

    double _percentage_height_default;

    double _width_for_rect_legend;
    double _height_for_rect_legend;

    double _max_width;

public:
    /*
     * \brief The default constructor
     */
    DrawStats() {
        _size_for_one_container = _HEIGHT_FOR_ONE_CONTAINER_DEFAULT;
        set_geometrical_informations();
    }

    
    /*!
     * \brief The destructor
     */
    virtual ~DrawStats() = default;


    /*!
     * \fn build(T* draw_object, std::vector<Container *> containers_to_print)
     * \brief The trace building function.
     * \param draw_object the kind of object which will be drawn (OpenGL, SVG...).
     * \param containers_to_print the container's data.
     */
    virtual void build(T* draw_object, std::vector<Container *> containers_to_print) = 0;

    /*!
     * \fn end_draw(T* draw_object)
     * \brief Set the end of the draw.
     * \param draw_object the kind of object which will be drawn (OpenGL, SVG...).
     */
    inline void end_draw(T* draw_object) {
        _previous_start_time = _start_time;
        _previous_end_time   = _end_time;
        draw_object->end_draw();
    }

    /*!
     * \fn set_times(const double start, const double end)
     * \brief Set the beginning and ending times of the draw.
     */
    inline void set_times(const double start, const double end) {
        _start_time = start;
        _end_time   = end;
    }

    /*! 
     * \fn get_max_percentage(std::map<const EntityValue*, stats*> &temp_states) const
     * \brief Get the biggest percentage of times for all the stats
     * \param temp_states The stats where we want to get the longest
     * \return a value between 0. and 1.
     *
     */
    virtual double get_max_percentage(std::map<const EntityValue*, stats*> &temp_states) const {
        double value;
        double max_length = 0.;
        for (auto & temp_state : temp_states) {
            if(temp_state.second->_total_length >= max_length) {
                max_length = temp_state.second->_total_length;
            }
        }
        value = max_length/(_end_time-_start_time);

        //std::cerr << value << std::endl;
       return value;
    }

    /*! 
     * \fn updateGL(T* draw_object) const
     * \brief Update the render window(only for OpenGL render)
     * \param draw_object the kind of object which will be drawn (OpenGL, SVG...).
     */
    virtual void updateGL(T* draw_object) const {
        draw_object->updateGL();
    }

    /*! 
     * \fn set_geometrical_informations()
     * \brief Set some infos for the displaying
     */
    virtual void set_geometrical_informations() {
        _pos_x_container_name = _POS_X_CONTAINER_NAME;
        _pos_y_container_name = _POS_Y_CONTAINER_NAME;
        
        _percentage_height_default = (_size_for_one_container - _START_HISTOGRAM_Y_DEFAULT - 20) / 100.;
     
        /* Size for rectangles in the legend */
        _width_for_rect_legend = 20.;
        _height_for_rect_legend = 15.;
        _max_width = 0;
    }

    /*! 
     * \fn set_geometrical_informations_object(T* draw_object)
     * \brief Set the total width and height for one container for the draw object
     * \param draw_object The kind of object which will be drawn (OpenGL, SVG...).
     */
    virtual void set_geometrical_informations_object(T* draw_object) {
        draw_object->set_total_width(this->_max_width);
        draw_object->set_height_for_one_container(this->_size_for_one_container);
    }
};
    
#endif
