/**
 * @author patrick ryan   www.agavegroup.com
 */


/**
 * this function receives the data and the paramaters that define the sparkline
 * @param data: an array of numbers: defines the sparkline's data points from left to right
 * @param parameters: an object of parameters.  object defined as follows:
 * 
 * 			parameter		default		allowed values				comments
 * 			-----------		---------	-----------------			---------------------	
 *LINE
 * 			height			20			integer						height of the graphic to be inserted in pixels
 * 			width			100			integer						width of the graphic to be inserted in pixels
 * 			lineColor		black		html color, text or hex		defines the color of the line - keep in mind, the line is thin - so black becomes grey - just due to size/resolution
 * 			lineWeight		4			integer (0-9)				defines the thickness of the plotted line.  Allowed values are 0-9.  Recommend something between 3 and 6
 *OUTPUT 
 * 			output			write		"write", "object"			defines how the graphic will be inserted on screen.  "write" simply does document.write in place.  "object" inserts the graphic in a given element on the page.  If "object" is passed, "outputId" is REQUIRED
 * 			outputId						string - id of element		required when "output" is "object".   This is the ID of an element on the page.  Graphic will be inserted (appended to) this element
 * 			suppressErrors	false		true, false					prevents errors from being alerted (may be used in production environment where you might want these errors to go unhandled). By default, errors are alerted.
 *MIN/MAX
 * 			showMin			false		true, false					determines whether min point is highlighted
 * 			minColor			red			html color, text or hex		defines the color of the min point (ignored if "showMin" is false)
 * 			showMax			false		true, false					determines whether max point is highlighted
 * 			maxColor			green		html color, text or hex		defines the color of the max point (ignored if "showMax" is false)
 *END POINT
 * 			showEndPoint		true			true, false					determines whether end point is highlighted
 * 			endPointColor	blue			html color, text or hex		defines the color of the end point (ignored if "showEndPoint" is false)
 * 			showEndValue		false		true, false					determines whether the end value is displayed on the graphic
 * 			endValueColor	black		html color, text or hex		defines the color of the end value text (ignored if "showEndValue" is false)
 * 			endValueFontSize	9			integer						defines the font size of the end value in px.  Note if you go too big, it can go outside the bounds of the graphic and get clipped. A problem for another day perhaps..
 *HOOKS
 *			objectId			-none-		valid elementId				defines the id of the <object> that will be inserted.  Can then be used for CSS rules or javascript manipulation
 *			objectClass		-none-		valid className				defines the className of the <object> that will be inserted.  Can then be used for CSS ruls
 */

function insertSparkline(data, parameters){
	//set defaults
	var width=100;
	var height=20;
	var lineColor="black";
	var lineWeight=4;
	var output="write";
	var outputId="";
	var suppressErrors=false;
	var showMin=false;
	var minColor="red";
	var showMax=false;
	var maxColor="green";
	var showEndPoint=true;
	var endPointColor="blue";
	var showEndValue=false;
	var endValueColor="black";
	var endValueFontSize=9;
	var objectId="";
	var objectClass="";
	
	//collect any passed parameters
	if(parameters){
		if(typeof parameters.width != "undefined"){ width = parameters.width;}
		if(typeof parameters.height != "undefined"){ height = parameters.height;}
		if(typeof parameters.lineColor != "undefined"){ lineColor = parameters.lineColor;}
		if(typeof parameters.lineWeight != "undefined"){ lineWeight = parameters.lineWeight;}
		if(typeof parameters.output != "undefined"){ output = parameters.output;}
		if(typeof parameters.outputId != "undefined"){ outputId = parameters.outputId;}
		if(typeof parameters.suppressErrors != "undefined"){ suppressErrors = parameters.suppressErrors;}
		if(typeof parameters.showMin != "undefined"){ showMin = parameters.showMin;}
		if(typeof parameters.minColor != "undefined"){ minColor = parameters.minColor}
		if(typeof parameters.showMax != "undefined"){ showMax = parameters.showMax;}
		if(typeof parameters.maxColor != "undefined"){ maxColor = parameters.maxColor;}
		if(typeof parameters.showEndPoint != "undefined"){ showEndPoint = parameters.showEndPoint;}
		if(typeof parameters.showEndValue != "undefined"){ showEndValue = parameters.showEndValue;}
		if(typeof parameters.endValueColor != "undefined"){ endValueColor = parameters.endValueColor;}
		if(typeof parameters.endValueFontSize != "undefined"){ endValueFontSize = parameters.endValueFontSize;}
		if(typeof parameters.objectId != "undefined"){ objectId = parameters.objectId;}
		if(typeof parameters.objectClass != "undefined"){ objectClass = parameters.objectClass;}
	}
	
	
	//before moving on, check that the data is valid: exists and has at least 2 points to plot
	if(!data){
		if(!suppressErrors){
			window.alert("error:\n\nNo data has been passed!");
		}
		return false;
	}
	if(data.length<2){
		if(!suppressErrors){
			window.alert("error:\n\nThere is not enough data passed.  At least 2 data points are required");
		}
		return false;
	}
	
	

	// create some margins for the chart  Without this (for example:) a circle drawn ON the border will be cut in half (half being outside the object)
	// this could be made into a parameter, but incorrect values can lead to confusing results - so if you want space around the graphic, I suggest giving the object an id or classname so you can move it with CSS
	var chartMargin=3;
	
	
	
	//determine possible difference between line length, and graphic width
	var scaleWidth=width;		//the width of the actual line
	if(showEndValue){ scaleWidth = width-15;}		//want to show last number, leave room by reducing width
	
	
	//get some statistics on the dataset
	var total = 0;
	var min = 999999;
	var max = -999999; 
  
	for (var i=0; i<data.length; i++) { 
		total = total + data[i];
		if (data[i] > max){ max = data[i];}
		if (data[i] < min){ min = data[i];}
	}
	var avg = total/data.length;
	  
	
	
	//want the final chart the same height as the passed "height" parameter.
	//  so the min and max numbers should be sitting on the bottom and top borders
	var totalVerticalGraphAmount = max-min;
	vertScale = (height-(2*chartMargin))/totalVerticalGraphAmount;
	
	//want to have the final chart the same width as the passed "width" parameter
	//  so, for each point should be equally spaced such that when complete, the full width is used
	var horizScale = (scaleWidth-(2*chartMargin))/(data.length-1);
	
	
	//develop the polyLine points
	var polyLinePoints = "";
	var lastHorizPoint=0;
	var lastVertPoint=0;
	var minHorizPoint=99999;
	var maxHorizPoint=-99999;
	var minVertPoint=99999;
	var maxVertPoint=-99999;
	var maxVertData=-99999;
	var minVertData=99999;
	for (var i=0; i<data.length; i++) {
		//the "max-n" is because this "plots" from the top of the box DOWN - not bottom UP
		//if thinking in terms of x,y - define X
		lastHorizPoint = i*horizScale;
		//define Y
		lastVertPoint = ((max-data[i])*vertScale)+chartMargin;
		
		//build polyLine
		polyLinePoints += ' ' + lastHorizPoint + ',' + lastVertPoint;	
		
		//capture min and max PLOTTED points
		if(data[i] > maxVertData){
			maxVertData=data[i];
			maxHorizPoint = lastHorizPoint;
			maxVertPoint = lastVertPoint;
		}
		if(data[i] < minVertData){
			minVertData=data[i];
			minHorizPoint = lastHorizPoint;
			minVertPoint = lastVertPoint;
		}
	} 
                                            
	
	//build the SVG code 
	var svgSrc=""
	//svgSrc += '<line x1="' + 0 + '" y1="'+ chartavg +'" x2="' + (chart.length-1) + '" y2="' + chartavg + '" style="stroke-width: 0.1; stroke-opacity: 0;"/>'; 
	svgSrc += '<polyline points="'+ polyLinePoints +'" style="stroke:'+lineColor+'; stroke-width:.'+lineWeight+'; fill:none;"/>';
	
	                                          
	//last point
	if(showEndPoint){
		svgSrc += '<circle cx="'+lastHorizPoint+'" cy="'+lastVertPoint+'" r="2" stroke="0" fill="'+endPointColor+'"/>';
	}
	
	//min and max points
	if(showMin){
		svgSrc += '<circle cx="'+ minHorizPoint +'" cy="'+ minVertPoint +'" r="2" stroke="0" fill="'+minColor+'"/>';
	}
	if(showMax){
		svgSrc += '<circle cx="'+ maxHorizPoint +'" cy="'+ maxVertPoint +'" r="2" stroke="0" fill="'+maxColor+'"/>';
	}

	//end value
	if(showEndValue){
		svgSrc += '<text x="'+ (lastHorizPoint+ 3) +'" y="'+ (lastVertPoint+3) +'" font-size="'+endValueFontSize+'" fill="'+endValueColor+'" font-weight="bold" font-family="Gill-sans">'+data[data.length-1]+'</text>';
	}
	
	//determine how to write the graphic
	if(output=="object"){
		// have chosen object - make sure the element exists
		if(!outputId){
			if(!suppressErrors){
				window.alert("error:\n\nWhen defining the \"output\" parameter as \"object\", you must define the \"outputId\" parameter.\n\nThis parameter should be the unique ID of an element on your page ");
			}
			return false;
		}
		if(!document.getElementById(outputId)){
			if(!suppressErrors){
				window.alert("error:\n\nYou passed '"+outputId+"' as the \"outputId\" parameter.  This ID does not correspond to an existing element on your page.\n\nPlease double check your ID. ");
			}
			return false;
		}
		//insert the graphic
		insertSVG(svgSrc, outputId, width, height, objectId, objectClass)
		
	}else{
		//write the graphic
		writeSVG(svgSrc, width, height, objectId, objectClass);
	}
}
	
	
//this function inserts any valid SVG string into the page - in the given holder, with the given height and width
function insertSVG(svgStr, holder, width, height, idNm, classNm){
	var svgStart='<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">';
	var svgEnd = '</svg>';
	
	var finalSVG= svgStart + svgStr + svgEnd;
	
	var svgObject = document.createElement('object');
		svgObject.setAttribute('name', 'svgObj');
		svgObject.setAttribute('id', idNm);
		svgObject.setAttribute('class', classNm);
		svgObject.setAttribute('codebase', 'http://www.adobe.com/svg/viewer/install/');
		svgObject.setAttribute('classid', 'clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2');
		svgObject.setAttribute('data', 'data:image/svg+xml,'+ finalSVG);
		svgObject.setAttribute('width', width);
		svgObject.setAttribute('height', height);
		svgObject.setAttribute('type', 'image/svg+xml');
	
		document.getElementById(holder).appendChild(svgObject);
}

//this function writes the SVG object with the given height and width
function writeSVG(svgStr, width, height, idNm, classNm){
	var svgStart='<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">';
	var svgEnd = '</svg>';
	
	var finalSVG= svgStart + svgStr + svgEnd;
	
	var svgObject= "<object id='"+idNm+"' class='"+classNm+"' name='svgObj' codebase='http://www.adobe.com/svg/viewer/install/'  classid='clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2'  data='data:image/svg+xml,"+ escape(finalSVG) + "' width='"+width+"' height='"+height+"'  type='image/svg+xml' ></object>";
	
	document.write(svgObject);
}


//the following two functions are only run from within the sparklines article
function runDemoSparkline(){
	myDataToPlot=[1,3,5,-3,10, 14, 15, 9, 7, 11, 5, 4, -3, -5, -10, 4, 7, 12];
	myParameters={"height":20,"width":200,"output":"write","lineColor":"red","lineWeight":4,"showMin":true,"minColor":"red","showMax":true,"maxColor":"green","showEndPoint":true,"endPointColor":"blue","showEndValue":true,"endValueColor":"black"}
	insertSparkline(myDataToPlot, myParameters);
}
function writeArticleRedDot(){
	var svgStr='<circle cx="50" cy="50" r="30" fill="red"/>';
	var svgStart='<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">';
	var svgEnd = '</svg>';
	var finalSVG= svgStart + svgStr + svgEnd;
	var svgObject= "<object name='svgObj' codebase='http://www.adobe.com/svg/viewer/install/'  classid='clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2'  data='data:image/svg+xml,"+ escape(finalSVG) + "' width='100' height='100'  type='image/svg+xml' ></object>";
	document.write(svgObject);
}
			
			