/******************************************************************************
 *                                                                            *
 *  Copyright (C) 2008-2010 Alexander Barth <barth.alexander@gmail.com>.      *
 *                                                                            *
 *  This program is free software: you can redistribute it and/or modify      *
 *  it under the terms of the GNU Affero General Public License as published  *
 *  by the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                       *
 *                                                                            *
 *  This program is distributed in the hope that it will be useful,           *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 *  GNU Affero General Public License for more details.                       *
 *                                                                            *
 *  You should have received a copy of the GNU Affero General Public License  *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.     *
 *                                                                            *
 ******************************************************************************/

function log10(x) {
    return Math.log(x)/Math.LN10;
}


// Propose about n ticks for range (min,max)
// Code taken from yapso

function ticks(min,max,n) {
    var nt;

    // a least 2 ticks
    if (n<2) n = 2;

    range = max-min;
    dt = range/n;
 
    // transform dt in "scientific notation"
    // dt = sdt * 10^(log10(base))

    base = Math.pow(10.0,Math.floor(log10(dt)) );
    sdt = dt/base;

    // pefered increments

    if (sdt <= 1.5) 
	sdt = 1;
    else if (sdt < 2.5) 
	sdt = 2;
    else if (sdt <= 4)
	sdt = 3;
    else if (sdt <= 7)
	sdt = 5;
    else
	sdt = 10;

    
    var dt = sdt * base;

    // the first label will be:  ceil(min/dt)*dt
    // the last label will be: floor(max/dt)*dt

    var t0 = Math.ceil(min/dt)*dt;

    // the difference between first and last label 
    // gives the number of labels

    nt = Math.round(Math.floor(max/dt) - Math.ceil(min/dt) +1);

    var t = new Array(nt);

    for(var i=0;i<nt;i++) {
	t[i] = t0 + i*dt;

	// attempt to remove spurious decimals
	var eps = dt;
	t[i] = Math.round(t[i]/eps)*eps;
	if (Math.abs(t[i])<1e-14) t[i]=0;
    }

    return t;
  
}

function remove_spurious_decimals(s) {
    if (typeof(s) == "number")
	s = s + "";

    re1 = new RegExp("(\\.[0-9]*[1-9]+)0{4,}.*$");

    s2 = s.replace(re1,"$1");

    re2 = new RegExp("(\\.)0{4,}.*$");
    s3 = s2.replace(re2,"$1");
    return s3;
}

// create labels using DOM functions

function label_DOM(ca0,ca1,level,orientation,tickslabelclass,ticksclass,len) {
    var pos,
	heigth = len -2,
	label,
	s,
	tick;

    //  alert("pos " + pos);

    label = document.createElement("div");

    s = remove_spurious_decimals("" + level);
    label.appendChild(document.createTextNode(s));
    label.className = tickslabelclass;

    tick = document.createElement("div");
    tick.className = ticksclass;

    if (orientation == "y") {
	pos = Math.round((ca1-level)/(ca1-ca0)*heigth);
	label.style.top = pos + "px";
	tick.style.top = pos + "px";
    }
    else {
	pos = Math.round((level-ca0)/(ca1-ca0)*heigth);
	label.style.left = pos + "px";
	tick.style.left = pos + "px";
    }

    return [label,tick];
}



function draw_ticks(ca0,ca1,labelid,orientation,tickslabelclass,ticksclass,len) {
    var t = ticks(ca0,ca1,6);

    var labels = document.getElementById(labelid);

    // remove all labels
    while (labels.hasChildNodes()) {
	labels.removeChild(labels.lastChild);
    }

    // add new labels
    for(var i=0;i<t.length;i++) {
	labeltick = label_DOM(ca0,ca1,t[i],orientation,tickslabelclass,ticksclass,len);
	labels.appendChild(labeltick[0]);
	labels.appendChild(labeltick[1]);
    }

}


function Axis(id,orientation,options) {
    this.id = id;
    this.orientation = orientation;

    // options
    this.tickslabelclass = "tickslabel";
    this.ticksclass = "ticks";
    this.vmin = -1;
    this.vmax = 1;

    if (options) {
	for (var p in options) {
	    this[p] = options[p];
	}
    }

    // update label if wind is resized
    var obj = this;
    $(window).bind('resize',function() { obj.draw(); });    
}

Axis.prototype.def_len = function() {
    if (this.orientation == "y")
	this.len = document.getElementById(this.id).offsetHeight-2;
    else
	this.len = document.getElementById(this.id).offsetWidth-2;

    //alert("len " + this.len);
};    


Axis.prototype.set_class = function(classname) {
    document.getElementById(this.id).className = classname;
};    

Axis.prototype.set_range = function(vmin,vmax) {
    this.vmin = vmin;
    this.vmax = vmax;
    this.draw();
};

Axis.prototype.draw = function() {    
    this.def_len();	

    if (this.len > 0) {
	draw_ticks(this.vmin,this.vmax,this.id,this.orientation,
		   this.tickslabelclass,this.ticksclass,this.len);
    }
};


