/*
** 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 Geometry.cpp
 */

#include <algorithm>  /* for min and max functions */
/* -- */
#include "common/common.hpp"
#include "common/Info.hpp"
/* -- */
#include "render/Geometry.hpp"


using namespace std;

#define message *Message::get_instance() << "(" << __FILE__ << " l." << __LINE__ << "): "


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

Geometry::Geometry(){

    init_geometry();  

    /* Camera is placed on (0,0,0) and looks to (0,0,-1) */

    _z_ruler_over      = -0.4; 
    _z_ruler           = -0.5;
    _z_ruler_under     = -0.6;    
    _z_container       = -1.0;
    _z_container_under = -1.2;
    _z_arrow           = -3.0;/* closer to camera than containers or states (MUST be negative)*/
    _z_event           = -2.0;/* closer to camera than containers or states (MUST be negative)*/
    _z_counter         = -4.0;    
    _z_state           = -5.0;
}


Geometry::~Geometry(){
}



 /***********************************
  *
  *
  *
  * Init function.
  *
  *
  *
***********************************/

void Geometry::init_geometry(){

    _counter_last_x = 0.0;
    _counter_last_y = 0.0;

    /* init main informations about OpenGL scene and QGLWidget size */
    _x_scale_container_state = 0.2;/* 20% of screen is used for containers then the other part for states */

    _ruler_height = 8.5; /* height of the ruler   */
    _ruler_y      = 0.0; /* highness of the ruler */

    _default_entity_x_translate =  20;/* Info::Render::width * _x_scale_container_state */
    
    _state_y_max = 0;
    _state_y_min = 0;

    _x_state_scale     = 1;/* for states scaling */
    _x_state_translate = 0;/* for states translation */
    _y_state_scale     = 1;/* for states scaling */
    _y_state_translate = 0;/* for states translation */
    _x_scroll_pos      = 0;/* horizontal bar placed on 0 */
    _y_scroll_pos      = 0;/* vertical bar placed on 0 */
}

/***********************************
  *
  *
  *
  * Coordinate convert functions.
  *
  *
  *
  **********************************/


Element_pos Geometry::screen_to_render_x(Element_pos e) const {

    return e * coeff_screen_render_x();
}

Element_pos Geometry::screen_to_render_y(Element_pos e) const {

    return e * coeff_screen_render_y();
}

Element_pos Geometry::render_to_trace_x(Element_pos e) const {
    return (e - _default_entity_x_translate + _x_state_translate) /
        coeff_trace_render_x();
}

Element_pos Geometry::render_to_trace_y(Element_pos e) const {

    return  (e-_ruler_y-_ruler_height + _y_state_translate) /
        coeff_trace_render_y();
}

Element_pos Geometry::render_to_screen_x(Element_pos e) const {

    return e / coeff_screen_render_x();
}

Element_pos Geometry::render_to_screen_y(Element_pos e) const {

    return e / coeff_screen_render_y();
}

Element_pos Geometry::trace_to_render_x(Element_pos e) const {

    return e * coeff_trace_render_x() +
            _default_entity_x_translate - _x_state_translate;
}

Element_pos Geometry::trace_to_render_y(Element_pos e) const {

    return  e *coeff_trace_render_y()  +
             _ruler_y + _ruler_height - _y_state_translate;
}

Element_pos Geometry::coeff_screen_render_x() const {
    return Info::Render::width / (Element_pos)Info::Screen::width;
}

Element_pos Geometry::coeff_screen_render_y() const {
    return Info::Render::height / (Element_pos)Info::Screen::height;
}


Element_pos Geometry::coeff_trace_render_x() const {

    return ((Info::Render::width-_default_entity_x_translate)*_x_state_scale) / (Info::Entity::x_max - Info::Entity::x_min);
}

Element_pos Geometry::coeff_trace_render_y() const {

    return ((Info::Render::height-_ruler_height)*_y_state_scale) / (Info::Container::y_max - Info::Container::y_min);
}



void Geometry::update_visible_interval_value() const {
    Info::Render::_x_min_visible = max(Info::Entity::x_min, (_x_state_translate - _default_entity_x_translate                      )/coeff_trace_render_x());
    Info::Render::_x_min=max(Info::Entity::x_min, _x_state_translate/coeff_trace_render_x());
    Info::Render::_x_max=min(Info::Entity::x_max, (_x_state_translate- _default_entity_x_translate + Info::Render::width)/coeff_trace_render_x());
    Info::Render::_x_max_visible = min(Info::Entity::x_max, (_x_state_translate - _default_entity_x_translate + Info::Render::width)/coeff_trace_render_x());
}
/*
Element_pos Geometry::visible_screen_x_min(){
    return trace_to_render_x(render_to_screen_x(Info::Render::_x_min_visible));
}

Element_pos Geometry::visible_screen_x_max(){
    return trace_to_render_x(render_to_screen_x(Info::Render::_x_max_visible));
}

Element_pos Geometry::visible_screen_y_min(){
}

Element_pos Geometry::visible_screen_y_max(){
}
*/
