/*
GraphDataSet is a container for an array of Point objects and tracks
the min and max values for x and y axis and allows no. of d.p. to be
specified for the returned Point array
*/
function GraphDataSet(title) {
		
	var minX = 0;
	var maxX = 0;
	var minY = 0;
	var maxY = 0;
	
	var decimalPlaces = 2;	
	var asPercentage = false;
	var coordinates = new Array();			
	
	this.title = title;
	
	var calcPercentage = function (min, max, x) { 
		return ((Number(x) - Number(min))/(Number(max) - Number(min)))*100; 
	}
	
	/* 
	Immutable point object maps a x/y coordinate and can apply any shifts to the 
	to its value defined in the parent dataset e.g. no. d.p and return y values
	as percentage of the maximum
	*/	
	var Point = function(x,y) {		
		var x = x;
		var y = y;
				
		this.getX = function() {return asPercentage ? calcPercentage(minX, maxX, x).toFixed(decimalPlaces) : x.toFixed(decimalPlaces);}
		this.getY = function() {return asPercentage ? calcPercentage(minY, maxY, y).toFixed(decimalPlaces) : y.toFixed(decimalPlaces);}

		this.getUnadjustedX = function() {return x;};		
		this.getUnadjustedY = function() {return y;};
	}
	
	this.setDecimalPlaces = function(x){decimalPlaces = x;};
	this.setAsPercentage = function(x){asPercentage = x;};
	this.getMinX = function(){return minX.toFixed(decimalPlaces);};
	this.getMaxX = function(){return maxX.toFixed(decimalPlaces);};
	this.getMinY = function(){return minY.toFixed(decimalPlaces);};
	this.getMaxY = function(){return maxY.toFixed(decimalPlaces);};
	
	//Interpolate position of y=0 as percentage relative to minY and maxY
	this.getZeroYPositionAsPercentage = function(){return calcPercentage(minY, maxY, 0);};
	this.getZeroXPositionAsPercentage = function(){return calcPercentage(minX, maxX, 0);};
	
	//Return the array of Point objects	
	this.getCoordinates = function() {return coordinates;};	
	
	/*
	Return a reference to the Point constructor to allow new Points to be intitialized
	Client code can add Points to the GraphDataSet as follows:
			
		var dataSet = new GraphDataSet();
		Point = dataSet.getPoint();
		dataSet.addCoordinate(new Point(x,y));
		
	*/
	this.getPointConstructor = function(){return Point;};
	
	//Add a new Point object to the GraphDataSet
	this.addCoordinate = function(point) {	
			coordinates.push(point);

			minX = Math.min(minX,point.getUnadjustedX());
			maxX = Math.max(maxX,point.getUnadjustedX());				
			minY = Math.min(minY,point.getUnadjustedY());
			maxY = Math.max(maxY,point.getUnadjustedY());
	}	
}

function graphDataSetBuilder(minX, maxX, interval, graphFunction) {
	return function() {
		var dataSet = new GraphDataSet(String(graphFunction));
		for (x = minX; x <= maxX; x += interval) {
				y = graphFunction(x);			
				
				if (!isFinite(y)) {
					continue;
				}					
				Point = dataSet.getPointConstructor();
				dataSet.addCoordinate(new Point(x,y));
			}					
		return dataSet;							
	}	
}

function googleIt(dataSet) {
	coordinates = dataSet.getCoordinates();
	xArray = new Array();
	yArray = new Array();
	
	dataSet.setDecimalPlaces(2);
	dataSet.setAsPercentage(true);
		
	for (coordinate in coordinates) {
		point = coordinates[coordinate];
		xArray.push (point.getX());
		yArray.push (point.getY());
	}	
	
	return "http://chart.apis.google.com/chart?cht=lxy&chs=300x200&chd=t:"
		+ "0,100|" + dataSet.getZeroYPositionAsPercentage()+ "," + dataSet.getZeroYPositionAsPercentage() + "|" 
		+ dataSet.getZeroXPositionAsPercentage()+ "," + dataSet.getZeroXPositionAsPercentage() + "|" + "0,100|" 
		+ xArray.join(",") + "|" + yArray.join(",")
		+ "&chco=BBBBBB,BBBBBB,336699"
		+ "&chls=1,3,3|1,3,3|1,1,0"
		+ "&chxt=x,y"
		+ "&chxr=0,"+ dataSet.getMinX() + "," + dataSet.getMaxX() + "|1," + dataSet.getMinY() + "," + dataSet.getMaxY()
		+ "&chtt=" + dataSet.title;
}

