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

#include <cmath>
#include <sstream>
/* -- */
#include "common/common.hpp"
#include "common/Info.hpp"
/* -- */
#include "render/Ruler.hpp"


using namespace std;


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




/***********************************
 *
 *
 *
 * Ruler methods.
 *
 *
 *
 **********************************/


Element_pos Ruler::get_graduation_diff(const Element_pos min, const Element_pos max){
    Element_pos diff;
    char step;
    Element_pos adjust;
    char security_counter;
    
    diff = max - min;
    adjust = 1;
    step = 0;
    security_counter = 0;

    if (diff==0.0) return 0.0;
    
    while((diff>100) && (security_counter<20)){
        diff   /= 10;
        adjust *= 10;
        security_counter++;
    }
    
    /* It is not necessary to reinitialize security_counter */

    while((diff<10) && (security_counter<20)){
        diff *= 10;
        adjust /= 10;
        security_counter++;
    }
    

    diff /= 10; /* Now, diff is within [1;10] */
   
    
     if (diff > 7){/* Check within ] 7 ; 10 ] */
        step = 10;/* 10 trace units between each graduation */
        
     }else// if (diff > 3){/* Check within ] 3 ; 7 ] */
         step = 5;/* 5 trace units between each graduation */

     // }else //if (diff > 1){/* Check within ] 1 ; 3 ] */
     //    step = 2;/* 2 trace units between each graduation */
        
    // }else{
    //     step = 1;/* 1 trace unit between each graduation */
    // }

    return step*adjust;
}

Element_pos Ruler::get_coeff_for_common_prefix(Element_pos min, Element_pos max){
    bool common;/* store if the entire part of min andmax are equal or not */
    Element_pos coeff;
    char security_counter;

    coeff = 1;
    security_counter = 0;

    /* Set common value */  
    if ( floor(min) != floor(max) )
        common = false;
    else
        common = true;
 
    if (common){
        /* common value is set. Now, if it is true, it means that entire part of min and max are equals.
           So, min and max will be multiplied by 10 (shift coma to the right) until their entire part differs.
        */
        while( (floor(min) == floor(max)) && (security_counter<20) ){
            min *= 10;
            max *= 10;
            coeff *= 10;
            security_counter++;
        }

        security_counter = 0;
    }
    /* If common value differs, min and max will be divided by 10 (shift coma to the left) 
       until their entire part are equal. */
    while( (floor(min) != floor(max)) && (security_counter<20) ){
        min /= 10;
        max /= 10;
        coeff /= 10;
        security_counter++;
    }

    return coeff;
}


/* TODO: use cmath::modf() */

double Ruler::get_common_part(const Element_pos n, const Element_pos coeff_for_common_prefix){
    double common_part = floor(n*coeff_for_common_prefix);
    double common_part_without_coeff = common_part/coeff_for_common_prefix;

    if (  (floor(common_part_without_coeff) != common_part_without_coeff)   )/* there is a comma */
        return common_part_without_coeff;
    else 
        return common_part;
}

double Ruler::get_variable_part(const Element_pos n, const Element_pos coeff_for_common_prefix, const int nb_digit_after_comma){
    const double common_part = floor( (n*coeff_for_common_prefix - floor(n*coeff_for_common_prefix))*pow(10., nb_digit_after_comma));
    const double common_part_without_coeff = common_part/(coeff_for_common_prefix*pow(10., nb_digit_after_comma));

    if ( floor(common_part_without_coeff) != 0. )/* and there is numbers before comma */
        return common_part_without_coeff;
    else
        return common_part;
}


string Ruler::get_common_part_string(const Element_pos n, Element_pos coeff_for_common_prefix){
    double common_part;
    Element_pos buf;
    ostringstream buf_txt, result_txt;

    /**
     *
     * For n = 10.2034 and coeff_for_common_prefix = 100,
     * then common_part = 1020
     *
     */
    common_part = floor(n*coeff_for_common_prefix);

    buf_txt.str("");
    result_txt.str("");

    /* No forget comma in the case where "100." is the common prefix */
    if (coeff_for_common_prefix==1.0)
           buf_txt << ".";/* Add comma */

    /**
     * First case: if n = 0.0234 and common_part is 0.023,
     * Put "0.0" and after "23". (Otherwise, common_part will
     * be equal to 23, ignoring "0.0"!)
     */
    buf = n;

    if ( (buf != 0.0) && (floor(buf) == 0.) ){
        result_txt << "0.";
        buf *= 10;
    }

    while ( (buf != 0.0) && (floor(buf) == 0.) ){
        result_txt << "0";
        buf *= 10;
    }

    for (; common_part > 0 ; common_part = floor(common_part/10.)){

        buf_txt << ((int)common_part)%10;

        if (coeff_for_common_prefix < 1)
            coeff_for_common_prefix *= 10.0;
        else{
            coeff_for_common_prefix /= 10.0;

            if ( (coeff_for_common_prefix == 1.0) && (floor(common_part/10.)>0) )
                buf_txt << ".";/* Add comma */
        }
    }

    const string txt_str = buf_txt.str();

    for (string::const_reverse_iterator rit= txt_str.rbegin() ; rit < txt_str.rend(); rit ++)
        result_txt << *rit;


    return result_txt.str();
}
