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

#ifndef RENDER_STATS_SVG_HPP
#define RENDER_STATS_SVG_HPP

#ifdef _WIN32
	#include <algorithm>
#endif

class Render_stats_svg;

#define _RENDER_WIDTH_DEFAULT  550.f
#define _RENDER_HEIGHT_DEFAULT 300.f

#ifdef min
#undef min
#endif
#ifdef max
#undef max
#endif

/*!
 * \brief This class redefined the Svg export to display the trace.
 */
class Render_stats_svg : public Render_stats {

private:
    
    /*!
     * \brief Contains container text coordinates.
     */
    std::ofstream _svg_file;
    std::string   _filename;

    Element_pos _y_min;
    Element_pos _y_max;
    /*!
     * \brief Contains container text coordinates.
     */
    std::list<Element_pos> _text_pos;
    
    /*!
     * \brief Contains container strings.
     */
    std::list<std::string> _text_value;
    /*!
     * \brief Contains line coordinates : x, y, size_x, size_y.
     */
    std::list<Element_pos> _line_pos;
     /*!
     * \brief Contains rect coordinates : x, y, w, h, r, g, b.
     */
    std::list<Element_pos> _rect_pos;
   
public:

    /*!
     * \brief The default constructor
     */
    Render_stats_svg(std::string filename);
    
    /*!
     * \brief The destructor
     */
    virtual ~Render_stats_svg();
  
    /*!
     * \brief Proceeds with the initialization of draw functions.
     */
    
    void start_draw() override;

    /*!
     * \fn draw_text(const Element_pos x, const Element_pos y, const std::string value)
     * \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.
     */
    void draw_text(const Element_pos x, const Element_pos y, const std::string value) override;

    /*!
     * \fn draw_line(const Element_pos x, const Element_pos y, const Element_pos x2, const Element_pos y2)
     * \brief Draw a line.
     * \param x the x position of the origin.
     * \param y the y position of the origin.
     * \param x2 the x position of the other point.
     * \param y2 the y position of the other point.
     */
    void draw_line(const Element_pos x, const Element_pos y, const Element_pos x2, const Element_pos y2);

    /*!
     * \fn draw_horizontal_line(const Element_pos x, const Element_pos y, const Element_pos size_x)
     * \brief Draw a line.
     * \param x the x position of the origin.
     * \param y the y position of the origin.
     * \param size_x the length of the line.
     */
    void draw_horizontal_line(const Element_pos x, const Element_pos y, const Element_pos size_x);

    /*!
     * \fn draw_vertical_line(const Element_pos x, const Element_pos y, const Element_pos size_y)
     * \brief Draw a line.
     * \param x the x position of the origin.
     * \param y the y position of the origin.
     * \param size_y the length of the line.
     */
    void draw_vertical_line(const Element_pos x, const Element_pos y, const Element_pos size_y);

    /*!
     * \fn draw_axis(const Element_pos x, const Element_pos y, const Element_pos size_x, const Element_pos size_y)
     * \brief Draw axis.
     * \param x the x position of the origin.
     * \param y the y position of the origin.
     * \param size_x the length for the horizontal axis.
     * \param size_y the length for the vertical axis.
     */
    void draw_axis(const Element_pos x, const Element_pos y, const Element_pos size_x, const Element_pos size_y);
    /*!
     * \brief Draw a rectangle.
     * \param x the x position of the rectangle.
     * \param y the y position of the rectangle.
     * \param w the width of the rectangle.
     * \param h the height position of the rectangle.
     * \param r the red component color of the rectangle.
     * \param g the green component color of the rectangle.
     * \param b the blue component color of the rectangle.
     */
    void draw_rect(const Element_pos x, const Element_pos y, const Element_pos w, const Element_pos h, const Element_pos r, const Element_pos g, const Element_pos b);
    /*!
     * \fn end_draw()
     * \brief Proceeds with the end of draw functions.
     */
    void end_draw() override;
    
    /*!
     * \fn set_total_height(Element_pos h)
     * \brief Set the height of the render area.
     * \param h the new height.
     */
    void set_total_height(Element_pos h) override;

    /*!
     * \fn set_total_width(Element_pos w)
     * \brief Set the width of the render area.
     * \param w the new width.
     */
    void set_total_width(Element_pos w);


     /*!
     * \fn set_height_for_one_container(Element_pos)
     * \brief Useless for svg.
     */
    void set_height_for_one_container(Element_pos /*h*/) override{};
    
    /*!
     * \fn clear()
     * \brief Reinitialize the render.
     */
    void clear();


    /*!
     * \fn height()
     * \brief Return the height of the render area.
     */
    inline double height(){return _RENDER_HEIGHT_DEFAULT;}

    /*!
     * \fn width()
     * \brief Return the width of the render area.
     */
    inline double width(){return _RENDER_WIDTH_DEFAULT;}

    /*!
     * \fn updateGL()
     * \brief Unused for svg (openGL only)
     */
    void updateGL(){}

    /*!
     \fn fill_file
     \brief fill the svg output file with the data.
    */
    void fill_file();
};


inline void Render_stats_svg::start_draw(){
    _svg_file.open(_filename.c_str(), std::ofstream::out | std::ofstream::trunc);
    _svg_file <<  "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\"?>\n"
            <<  "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"  \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
            <<  "<svg xmlns=\"http://www.w3.org/2000/svg\" x=\"0\" y=\"0\" id=\"svg2\" style=\"background-color:#c1e9ed;\" >\n"
        ;
}

inline void Render_stats_svg::draw_text(const Element_pos x, const Element_pos y, const std::string value) {
    _y_min = std::min(y-5, _y_min);
    _y_max = std::max(y+5, _y_max);

    _text_pos.push_back(x);
    _text_pos.push_back(y);
    _text_value.push_back(value);
}

inline void Render_stats_svg::draw_line(const Element_pos x, const Element_pos y, const Element_pos x2, const Element_pos y2) {
    _y_min = std::min(std::min(y, y2), _y_min);
    _y_max = std::max(std::max(y, y2), _y_max);

    _line_pos.push_back(x);
    _line_pos.push_back(y);
    _line_pos.push_back(x2-x);
    _line_pos.push_back(y2-y);
}

inline void Render_stats_svg::draw_horizontal_line(const Element_pos x, const Element_pos y, const Element_pos size_x){
    _y_min = std::min(y, _y_min);
    _y_max = std::max(y, _y_max);

    _line_pos.push_back(x);
    _line_pos.push_back(y);
    _line_pos.push_back(size_x);
    _line_pos.push_back(0);
}

inline void Render_stats_svg::draw_vertical_line(const Element_pos x, const Element_pos y, const Element_pos size_y){

    _y_min = std::min(std::min(y, y+size_y), _y_min);
    _y_max = std::max(std::max(y, y+size_y), _y_max);

    _line_pos.push_back(x);
    _line_pos.push_back(y);
    _line_pos.push_back(0);
    _line_pos.push_back(size_y);
}

inline void Render_stats_svg::draw_axis(const Element_pos x, const Element_pos y, const Element_pos size_x, const Element_pos size_y){
    draw_horizontal_line(x, y, size_x);
    draw_vertical_line(x, y, size_y);
}

inline void Render_stats_svg::draw_rect(const Element_pos x, const Element_pos y, const Element_pos w, const Element_pos h, const Element_pos r, const Element_pos g, const Element_pos b) {

    _y_min = std::min(std::min(y, y+h), _y_min);
    _y_max = std::max(std::max(y, y+h), _y_max);

    _rect_pos.push_back(x);
    _rect_pos.push_back(y);
    _rect_pos.push_back(w);
    _rect_pos.push_back(h);
    _rect_pos.push_back(r);
    _rect_pos.push_back(g);
    _rect_pos.push_back(b);

}

inline void Render_stats_svg::end_draw(){
    fill_file();
    _svg_file << "</svg>\n";
    _svg_file.close();
}

#endif
