/* This notice must remain at all times.

graph.js
Copyright (c) Balamurugan S, 2005. sbalamurugan @ hotmail.com
Development support by Jexp, Inc http://www.jexp.com

This package is free software. It is distributed under GPL - legalese removed, it means that you can use this for any purpose, but cannot charge for this software. Any enhancements you make to this piece of code, should be made available free to the general public!

Latest version can be downloaded from http://www.sbmkpm.com

This library 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.

line.js provides a simple mechanism to draw line graphs. It  uses
wz_jsgraphics.js  which is copyright of its author.

Usage:
var g = new line_graph();
g.add("title1", value, "node title");
g.add("title2",value2, "node title");

g.render("canvas_name", "graph title");

//where canvas_name is a div defined INSIDE body tag
<body>
<div id="canvas_name" style="overflow: auto; position:relative;height:300px;width:400px;"></div>


*/


hD="0123456789ABCDEF";

//--->> start of BZ additions

function YourFunc( title )
{
   jg.drawString("BZ says "+title,4,10);
}
function turnOn( idx, my_elem ) 
{
		alert( my_elem );

    	if (document.images) {
 	 	 document["image2"].src = "image2.gif"; }
}

function turnOff() 
{
    if (document.images) {
//      document[imageName].src = eval(imageName + "off.src");
	  document["image2"].src = "blank.gif"; }
}

//---<< end of BZ additions

function d2h(d)
{
 var h = hD.substr(d&15,1);
 while(d>15) {d>>=4;h=hD.substr(d&15,1)+h;}
 return h;
}

function h2d(h) 
{
 return parseInt(h,16);
}


function line_graph( node_image )
{
 this.ct = 0;
 
 this.data      = new Array();
 this.x_name    = new Array();
 this.max       = -64000; //MAX INT
 this.titles	= new Array();

 this.c_array = new Array();
 this.c_array[0] = new Array(255, 192, 95);
 this.c_array[1] = new Array(80, 127, 175);
 this.c_array[2] = new Array(159, 87, 112);
 this.c_array[3] = new Array(111, 120, 96);
 this.c_array[4] = new Array(224, 119, 96);
 this.c_array[5] = new Array(80, 159, 144);
 this.c_array[6] = new Array(207, 88, 95);
 this.c_array[7] = new Array(64, 135, 96);
 this.c_array[8] = new Array(239, 160, 95);
 this.c_array[9] = new Array(144, 151, 80);
 this.c_array[10] = new Array(255, 136, 80);

 this.getColor = function()
  {
   if(this.ct >= (this.c_array.length-1))
      this.ct = 0;
   else
      this.ct++;

   return "#" + d2h(this.c_array[this.ct][0]) + d2h(this.c_array[this.ct][1]) + d2h(this.c_array[this.ct][2]);
  }


 this.add = function( x_name, value, title )
  {
   this.x_name.push( x_name );
   this.data.push( parseInt( value, 10 ));
   this.titles.push( title );

   if ( value > this.max )
      this.max = parseInt( value, 10 );
  }

 this.render = function( canvas, gr_title )
 {
	var jg = new jsGraphics(canvas);

	var h  = 250;
	var sx = 40;
	var dw = 15;
	var shadow = 0;
	var fnt    = 12;

   	var rtmax = sx + 10 + (dw+Math.round((dw/2))+shadow)*(this.data.length);

	// Draw markers

	var i;
	jg.setColor("black");

	for(i = 1 ; i <= 5 ; i++)
	{
		jg.drawLine(0,Math.round((h/5*i)),rtmax+20,Math.round((h/5*i)));
		var ff = Math.round(this.max - (this.max / 5 * i));
		jg.drawString(ff+"",4,Math.round((h/5*i)-2));
	}

   // Draw the line graph
   var color = this.getColor();
   var oldx, oldy;
   jg.setStroke(1);

   for(i = 0; i < this.data.length; i++)
      {
       var ht1 = Math.round(this.data[i]*h/this.max);

       if(i >= 1)
         {
          jg.setColor(color);
          jg.drawLine(oldx, h-oldy, sx, h-ht1);
	 }

       jg.setColor("red");
//       jg.fillEllipse(sx-2, h-ht1-2, 10, 10,"onmouseover=turnOn(); onmouseout=turnOff()");

		jg.drawImage( node_image, sx-5, h-ht1-5, 10, 10, '', this.titles[i] ); 

       jg.setColor("black");
       jg.drawString(this.x_name[i], sx, h);

       oldx = sx;
       oldy = ht1;

       sx = sx+dw+Math.round(dw/2)+shadow;
      }

   jg.setFont("Verdana", fnt,  Font.BOLD);
   jg.drawStringRect(gr_title, 0, h+fnt+4, rtmax+20, "right");
   jg.paint();
  }

}

//==========================================================================
// BZ additions: Jan-Feb 2007
//
// bz_line_graph based on line_graph
// it takes values of x also into considerataion.
//==========================================================================
function bz_line_graph( graph_width, graph_height, y_coef )
{
 this.ct = 0;
 
 this.titles	= new Array();
 this.x_data      = new Array();
 this.y_data      = new Array();

 this.data		= new Array();

 this.x_max       = -64000; //MAX INT
 this.y_max       = -64000; //MAX INT
 this.max       = -64000; //MAX INT
 this.height	= graph_height - 20;
 this.width		= graph_width - 30;


 this.marker_distances = new Array();
 this.marker_distances[ 0 ] = 1;
 this.marker_distances[ 1 ] = 2;
 this.marker_distances[ 2 ] = 5;

 this.no_of_x_markers = -1;
 this.x_markers_distance = -1;

 this.no_of_y_markers = -1;
 this.y_markers_distance = -1; 

 this.c_array = new Array();
 this.c_array[0] = new Array(255, 192, 95);
 this.c_array[1] = new Array(80, 127, 175);
 this.c_array[2] = new Array(159, 87, 112);
 this.c_array[3] = new Array(111, 120, 96);
 this.c_array[4] = new Array(224, 119, 96);
 this.c_array[5] = new Array(80, 159, 144);
 this.c_array[6] = new Array(207, 88, 95);
 this.c_array[7] = new Array(64, 135, 96);
 this.c_array[8] = new Array(239, 160, 95);
 this.c_array[9] = new Array(144, 151, 80);
 this.c_array[10] = new Array(255, 136, 80);

 this.getColor = function()
  {
   if(this.ct >= (this.c_array.length-1))
      this.ct = 0;
   else
      this.ct++;

   return "#" + d2h(this.c_array[this.ct][0]) + d2h(this.c_array[this.ct][1]) + d2h(this.c_array[this.ct][2]);
  }

 
 function sort_on_x( a, b )
 {
	return( a[ 0 ] - b[ 0 ] );
 }


 this.add = function( x_value, y_value, node_title )
 {
	this.data.push( [ parseInt( x_value, 10 ), parseInt( y_value, 10 ), node_title ] );


   if( x_value > this.x_max )
      this.x_max = parseInt( x_value ,10 );

   if( y_value > this.y_max )
      this.y_max = parseInt( y_value ,10 );
  }


 this.set_markers = function( max_val, is_x )
 {
	var n_markers_mult = 1;

	var marker_distance = -1; 
	var no_of_markers = -1;

	if ( max_val < 10 )
	{
		max_val = 10;
	}

	while  ( no_of_markers > 10 || no_of_markers < 5 )
	{
		for ( idx = 0; idx < this.marker_distances.length; idx++ )
		{
			var distance = this.marker_distances[ idx ] * n_markers_mult;
			var n_markers = Math.ceil( max_val / distance );

			if ( n_markers <= 10 && n_markers >= 5 )
			{
				no_of_markers = n_markers;
				markers_distance = distance;

				if ( is_x > 0 )
				{
					this.no_of_x_markers = no_of_markers;
					this.x_markers_distance = distance; 
					this.x_max = no_of_markers * distance;
				}
				else
				{ 
					this.no_of_y_markers = no_of_markers;
					this.y_markers_distance = distance; 
					this.y_max = no_of_markers * distance;
				}
			}
		}
		n_markers_mult *= 10;
	}
} 


 this.render = function( canvas, x_label, draw_lines, node_image, y_axis_image, abs_x_max, abs_y_max  )
  {

	if ( draw_lines > 0 )
		this.data.sort( sort_on_x );		// to connect each two points by a line

	var jg = new jsGraphics(canvas);
	jg.setColor("cyan");

	if ( this.data.length <= 0 )
	{
		if ( abs_x_max <= 0 ) 
			this.x_max = this.width;
		if ( abs_y_max <= 0 ) 
				this.y_max = this.height;
	}

	var h = this.height - 20;
	var w =	this.width - 20;

	var start_x = 55;
	var start_y = 10;
	var graph_w = w - start_x;
	var graph_h = h - 10;
	
	// BZ needs work:::::::::::   abs_y_max = abs_y_max / y_coef;

	if ( abs_x_max > this.x_max )
		this.x_max = abs_x_max;

	if ( abs_y_max > this.y_max )
		this.y_max = abs_y_max;

	this.set_markers( this.x_max, 1 );	// is_x = 1 (sets markers for x-axis)
	this.set_markers( this.y_max, -1 );	// is_x = -1 (sets markers for y-aixs)

  // Draw markers
	var i;

	var x_label_no = this.no_of_x_markers;
	var y_label_no = this.no_of_y_markers;

	// y-axis
	jg.drawLine( start_x, start_y - 5 , start_x, graph_h + start_y );

	for( i = 1; i <= x_label_no; i++ )		//sets markers on x-axis
	{
		var cur_x = i * this.x_markers_distance;
		var cur_x_loc = start_x + Math.round( cur_x * graph_w / this.x_max );

//		jg.drawLine( cur_x_loc , graph_h + start_y, cur_x_loc, graph_h + start_y + 5 );	// draws the markers on x-axis
		jg.drawLine( cur_x_loc , start_y, cur_x_loc, graph_h + start_y );	// draws the grid line

		jg.drawString( cur_x + "", cur_x_loc - 5 , graph_h + start_y + 5 );	// writes the marker values
	}

	// x-axis / horizental lines

	var line_max_x = start_x + Math.round( x_label_no * this.x_markers_distance * graph_w / this.x_max );
	
	for( i = 0; i <= y_label_no; i++ )		//sets markers on y-axis
	{
		var cur_y = i * this.y_markers_distance; 
		var cur_y_loc = start_y + graph_h - Math.round( cur_y * graph_h / this.y_max );

		if ( i == 0 )
			jg.drawLine( start_x , cur_y_loc, line_max_x + 10, cur_y_loc );
		else
			jg.drawLine( start_x , cur_y_loc, line_max_x, cur_y_loc );

		jg.drawString( cur_y/y_coef+"", start_x-30 , cur_y_loc - 5 );	// cur_y/100: because we store speed as 100*pixels/sec 
	}


   // Draw the line graph, or just the nodes 
   var color = this.getColor();
   var oldx, oldy;
   jg.setStroke(1);

	if ( this.data.length > 0)
	{
		oldx = start_x + this.data[ 0 ][ 0 ];
		oldy = start_y + graph_h - Math.round( this.data[ 0 ][ 1 ] * graph_h / this.y_max );
	}

	if ( x_label.length > 0 )				// when x-axis type is actually selected 
	for( i = 0; i < this.data.length; i++ )
	{
		var x_val = start_x + Math.round( this.data[ i ][ 0 ] * graph_w / this.x_max );
		var y_val = start_y + graph_h - Math.round( this.data[ i ][ 1 ] * graph_h / this.y_max );

		if ( draw_lines > 0 )
        {
			jg.setColor( color );
			jg.drawLine( oldx, graph_h - oldy, x_val, start_y + graph_h - y_val );
		}

		// image_title shows only the values of x and y: ( x , y )
		// var image_title = "( " + this.data[ i ][ 0 ] + " , " + this.data[ i ][ 1 ]/y_coef + " )";
		var image_title = this.data[ i ][ 2 ];
		jg.drawImage( node_image, x_val-5, y_val - 5, 10, 10, '', image_title ); 


		oldx = x_val;
		oldy = y_val;
	}
	
	jg.drawImage( y_axis_image, 0, 80, 25, 100 );
	jg.setColor( "#FFCC00" );
	jg.setFont( "Verdana", 14,  Font.BOLD );
	if ( x_label.length > 0 )
		jg.drawString( x_label+"", Math.round( graph_w / 2 - x_label.length / 2) , this.height );
	jg.paint();
 }
}


