
var Chart = {
	COLORS:['3333CC', 'C79E22', 'CC33CC', 'E40000', '00E0E8', '303030', 'E60022', 'B35F00'],
	COLORS2:['5A99CD', '8B6969', 'BBB53A'],
	COLORS3:['C03030', '8B6969'],
	COLORS4:['6B4226'],
	COLORS5:['215E21'],
	COLORS6:['CC33CC', 'C79E22', '3333CC'],
	COLORS7:['B00202', 'F7771B', '1EA619', '0909DE', 'A10EEB'],
	LINES:['3,1,0|3,1,0|3,1,0'],
	LINES1:['3,1,0|3,1,0|3,1,0'],
	LINES2:['3,1,0|1,10,6|3,1,0'],
	LINES3:['3,1,0|1,10,6|3,2,3'],
	MAX_PIXELS: 300000,
	charts:[],
	
	/* config in the form of: (all items are optional, though you'll get a blank chart if you don't specify any data or a renderTo id)
	{
		renderTo:'img_id',
		labels:[series1_label, series2_label, series3_label, ...],
		data:[
			[series1...],
			[series2...],
			[series3...],
			...
		],
		xAxis:{
			start:0,
			end:100,
			step:20,
			label:'X Axis Label'
		},
		yAxis:{
			start:0,
			end:1000,
			step:200,
			label:'Y Axis Label'
		},
		title:'Chart Title',
		size:[width,height]
	}
	*/
	LineChart:function(config) {
		// set config to empty objects if not defined
		config || (config = {});
		config.data || (config.data = [[]]);
		config.labels || (config.labels = []);
		config.xAxis || (config.xAxis = {});
		config.yAxis || (config.yAxis = {});
		config.size || (config.size = []);
		config.stacked || (config.stacked = {});
		config.legends || (config.legends = []);
		config.lines || (config.lines = []);
		config.alternateColors || (config.alternateColors = []);


		
		// set chart size (defaults to 300 x 200)  if too large, will scale it down
		var width = (config.size[0] ? config.size[0] : 300);
		var height = (config.size[1] ? config.size[1] : 200);
		if(width * height > Chart.MAX_PIXELS) {
			var coeff = Math.sqrt(Chart.MAX_PIXELS / width / height);
			height = Math.floor(coeff * height);
			width = Math.floor(coeff * width);
		}
		(width < 1000) || (width = 1000);
		(height < 1000) || (height = 1000);

		// get max series length for auto-calculating x-axis labels
		var maxSeriesLength = 0;
		for(var i=0;i<config.data.length;i++)
			(config.data[i].length > maxSeriesLength) && (maxSeriesLength = config.data[i].length);
		
		// get the value for stacked
		if(config.stacked == 1)
		{
			var stacked = true;
		} else {
			var stacked = false;
		}
		
		// get max and min values for y-axis labels, either through y-axis config or from data
		var maxValue = 0;
		var minValue = 0;
		if(config.yAxis.end) {
			maxValue = config.yAxis.end;
			minValue = config.yAxis.start ? config.yAxis.start : 0;
		} else {
			for(var i=0;i<config.data.length;i++) {
				for(var j=0;j<config.data[i].length;j++) {
					(config.data[i][j] < minValue) && (minValue = config.data[i][j]);
					(config.data[i][j] > maxValue) && (maxValue = config.data[i][j]);
				}
			}
			// pad the data, leaving room at top and bottom of chart
			maxValue /= .9;
			minValue < 0 && (minValue /= .9);
		}

		// normalize chart data
		var chartData = [];
		for(var i=0;i<config.data.length;i++) {
			for(var j=0;j<config.data[i].length;j++)
				config.data[i][j] = Math.round(1000 * (config.data[i][j] - minValue) / (maxValue - minValue)) / 10;
			chartData.push(config.data[i].join(','));
		}

		// setup y-axis labels
		var yAxisSteps = config.yAxis.step ? (maxValue-minValue) / config.yAxis.step : 5;
		var yAxisLabels = [];
		for(var i=0;i<=yAxisSteps;i++)
			yAxisLabels.push( Math.round( ( (maxValue-minValue) * i/yAxisSteps + minValue ) * 10 ) / 10 );

		// setup x-axis labels
		var xAxisMin = config.xAxis.start ? config.xAxis.start : 0;
		var xAxisMax = config.xAxis.end ? config.xAxis.end : maxSeriesLength - 1;
		var xAxisSteps = config.xAxis.step ? (xAxisMax-xAxisMin) / config.xAxis.step : 5;
		var xAxisLabels = [];
		for(var i=0;i<=xAxisSteps;i++)
			xAxisLabels.push( Math.round( ( (xAxisMax-xAxisMin) * i/xAxisSteps + xAxisMin ) * 10 ) / 10 );

		var multipleVars = chartData.length>1;
		
		// this function sorts an array of "stringed" numbers from 
		// greatest value set to lowest (based on the sum of all the 
		// numbers in each string) and returns the array
		this.sortData = function(values)
		{
			var addRecur = function(an)
			{
				var total = 0;
				for(j=0;j<an.length;j++)
				{
					total = total + Math.floor(an[j]);
				}
				return total;
			};

			var splitValues = [];
			var valuestring;
			var maxValue = 0;
			var totalVal = 0;
			var mx={};
			var tots = [];
			var sortedLegends = {};
			for(i=0;i<values.length;i++)
			{
				splitValues[i] = values[i].split(',')
				totalVal = addRecur(splitValues[i]);
				if(mx[totalVal]){
					mx[totalVal]["duplicate"] = true;
					mx[totalVal]["duplicateLegend"] = mx[totalVal]["legend"] ;
				}else{
					mx[totalVal] = {};
				}
				mx[totalVal]["value"] =values[i];
				
				mx[totalVal]["legend"] = config.legends[i]
				//sortedLegends[totalVal] = config.legends[i];
				tots.push(totalVal);
			}
			function sortNumber(a, b){
				return b - a;
			}
			
			tots.sort(sortNumber);

			var newArray =[];
				
			for(var k=0; k<tots.length; k++){

			   newArray.push(mx[tots[k]+""]["value"]);
			   var elemID = 'legend-'+k;
			   //console.log(mx, mx[tots[k]+""]["legend"]);'
			   if(mx[tots[k]+""]["duplicate"] != true)
			   {
			   	 document.getElementById(elemID).innerHTML = mx[tots[k]+""]["legend"];
			   }
			   else
			   {
			  	 	mx[tots[k]+""]["duplicate"] = false;
					document.getElementById(elemID).innerHTML = mx[tots[k]+""]["duplicateLegend"];
			   }
			  
			}
			return newArray;
		}


		//determine color set 

		if(config.alternateColors == 1){
			Chart.COLORS = Chart.COLORS2;
		}

		if(config.alternateColors == 2){
			Chart.COLORS = Chart.COLORS3;
		}
		
		if(config.alternateColors == 3){
			Chart.COLORS = Chart.COLORS4;
		}
        	
		if(config.alternateColors == 4){
			Chart.COLORS = Chart.COLORS5;
		}
        	
		if(config.alternateColors == 5){
			Chart.COLORS = Chart.COLORS6;
		}
		
		if(config.alternateColors == 6){
			Chart.COLORS = Chart.COLORS7;
		}
		
		// sort the data to be passed if the chart is going to be stacked
		if(stacked == true){
			//console.log("input data", chartData);
			chartData = this.sortData(chartData);
			
			// this bit of nonsense right here
			// creates an array of zeroes to be
			// pushed onto the end of the array
			// going to google chart's api...so 
			// the last data set can be filled 
			// into the bottom on the chart

			var holdZeros = [];
			for(m=0;m<=3;m++)
			{
				holdZeros.push(0,0);
			}
			chartData.push(holdZeros);
		
		
			//alert(chartData);
			
			// manipulate the colors of Chart.COLORS to eliminate an extra color at the bottom of the chart
			var fillVar = '&chm=';
			for(q=0;q<chartData.length;q++){
				if(q == chartData.length - 1)
				{
					fillVar += 'b,' + Chart.COLORS[q-1] + ',' + q + ','+ (q+1) + ',0';
					Chart.COLORS[q] = Chart.COLORS[q-1];
				} else {
					fillVar += 'b,' + Chart.COLORS[q] + ',' + q + ','+ (q+1) + ',0|';              //b,15B052,1,2,0|b,424563,2,3,0|b,424563,3,4,0';
				}
			}
			
			// var fillVar = '&chm=b,F37800,0,1,0|b,15B052,1,2,0|b,424563,2,3,0|b,424563,3,4,0';
		}else{
			var fillVar = '';
		}
		
		//determine line types 

		if(config.lines == 1){
			Chart.LINES = Chart.LINES1;
		}
		
		if(config.lines == 2){
			Chart.LINES = Chart.LINES2;
		}
		
		if(config.lines == 3){
			Chart.LINES = Chart.LINES3;
		}

       		// generate url

				this.render = function() {
		
					if(config.renderTo)
						{
					  	var requestUrl = 'http://chart.apis.google.com/chart' +
							// size
							'?chs=' + width + 'x' + height +
							// chart data
							'&chd=t:' + chartData.join('|') + 
							// if it's stacked, fill the areas
							fillVar +
							// chart type
							'&cht=lc' +
							// line type and size
							'&chls=' + Chart.LINES + '|3,1,0|3,1,0|3,1,0' +
							// line colors
							'&chco=' + Chart.COLORS.join(',') +
							// canvas color - shaded background every y-axis label
							'&chf=c,ls,90,FFFFFF,' + 1/yAxisSteps + ',F3F3F3,' + 1/yAxisSteps +
							// chart title
							(config.title ? '&chtt=' + config.title.split(' ').join('+'):'') + 
							// chart title style
							(config.titlestyle ? '&chts=' + config.titlestyle.split(' ').join(','):'') + 
							// chart legend
							(config.labels.length > 1 ? '&chdl=' + config.labels.join('|'):'') +
							// axes (if x-axis label specified, use secondary label for axis title, use third label for axis title if y-axis label specified)
							'&chxt=x,y' + (config.xAxis.label?',x':'') + (config.yAxis.label?',y':'') + 
							// axes labels
							'&chxl=0:|' + xAxisLabels.join('|') + '|1:|' + yAxisLabels.join('|') + (config.xAxis.label?'|2:|' + config.xAxis.label.split(' ').join('+'):'') + (config.yAxis.label?'|3:|' + config.yAxis.label.split(' ').join('+'):'') +
							// secondary x-axis label position (centered)
							(config.xAxis.label?'&chxp=2,50':'') +
							// secondary y-axis label position (centered)
							(config.yAxis.label?'&chxp=2,50':'') +
							// font colors and size
							'&chxs=0,4A4A4A,14|1,4A4A4A,14' +
							// grid lines
							'&chg=' + Math.round(100/xAxisSteps) + ',' + Math.round(100/yAxisSteps) + ',1,0';
							document.getElementById(config.renderTo).src  = requestUrl;
						} 
				}; 
			
		Chart.charts.push(this);
		this.render();
	}//end chart
}
/*
YAHOO.util.Event.onDOMReady(function() {
	for(var i=0;i<Chart.charts.length;i++)
		Chart.charts[i].render();
});

*/