// Every "GraphPlot" object has the following:
// x
// y
// minx, maxx
// miny, maxy
// ...?

MARGIN = 0.1;
PLOT_LINE_COLOR = "green";
PLOT_LINE_CHAR = "--.."; // Options: [“”, “-”, “.”, “-.”, “-..”, “. ”, “- ”, “--”, “- .”, “--.”, “--..”]
AXIS_LINE_WIDTH = 2;
POINT_RADIUS = 4;

function animateMouseClickPointData(paper, points, col) {

	CUR_OFFSET = 1;

	for (i = 0; i < points.length; i++) {
		
		points[i].click(function (event) {
			
			cur = getPosition(event);
			it = paper.text(cur.x + CUR_OFFSET, cur.y + CUR_OFFSET, this.yValue);
			it.attr({fill: "black"});
			it.attr({"font-size": 17});
			it.attr({"font-weight": 10});

			if (col) {
				this.attr({fill: col});
				this.attr({stroke: col});	
			}

		});
	}	
	
}


function animateMouseOverFill(points, oncol, offcol) {

	//document.write(points.length);
	
	for (i = 0; i < points.length; i++) {
		points[i].mouseover(function (event) {this.attr({fill: offcol});});	
		points[i].mouseout(function (event) {this.attr({fill: oncol});});
	}
	
	
}

function animateMouseOverStroke(points, oncol, offcol) {

	//document.write(points.length);
	
	for (i = 0; i < points.length; i++) {
		points[i].mouseover(function (event) {this.attr({stroke: offcol});});	
		points[i].mouseout(function (event) {this.attr({stroke: oncol});});
	}
	
	
}

function animateMousClickInfoText(paper, points, infotext, col) {

	CUR_OFFSET = 2;
	
	//it = paper.text(10, 10, "hello");
	//it.hide();

	for (i = 0; i < points.length; i++) {
		
		points[i].click(function (event) {
			cur = getPosition(event);
			it = paper.text(cur.x + CUR_OFFSET, cur.y + CUR_OFFSET, infotext);
			it.attr({fill: "black"});
			it.attr({"font-size": 15});
			it.attr({"font-weight": 2});
			
			if (col) {
				this.attr({stroke: col});	
			}
			
			//it.show();
		});
	}	
	
}

function animateMouseOverInfoText(paper, points, infotext) {

	CUR_OFFSET = 10;
	
	//it = paper.text(10, 10, "hello");
	//it.hide();

	for (i = 0; i < points.length; i++) {
		
		points[i].mouseover(function (event) {
			cur = getPosition(event);
			it = paper.text(cur.x + CUR_OFFSET, cur.y + CUR_OFFSET, infotext);
			it.attr({fill: "black"});
			it.attr({"font-size": 15});
			it.attr({"font-weight": 2});
			//it.show();
		});	
		points[i].mouseout(function (event) {
			it.remove();
			//it.hide();
		});
	}	
	
}

function animateMouseOverPointData(paper, points, prelabel) {

	CUR_OFFSET = 10;
	
	if (!prelabel) {
		prelabel = "";	
	}
	
	//it = paper.text(10, 10, "hello");
	//it.hide();

	for (z = 0; z < points.length; z++) {
		
		//document.write("<br>" + z);
		//lab = label + dy[z] + "";
		
		points[z].mouseover(function (event) {
			cur = getPosition(event);
			//document.write(z + "<br>" + dy[z] + "<br>" + dy);
			it = paper.text(cur.x + CUR_OFFSET, cur.y + CUR_OFFSET, this.yValue);
			it.attr({fill: "black"});
			it.attr({"font-size": 15});
			it.attr({"font-weight": 2});
			//it.show();
		});	
		points[z].mouseout(function (event) {
			it.remove();
			//it.hide();
		});
	}	
	
}

//function animateMouseOverText(points, 

// From: http://hartshorne.ca/2006/01/23/javascript_cursor_position/
function getPosition(e) {
    e = e || window.event;
    var cursor = {x:0, y:0};
    if (e.pageX || e.pageY) {
        cursor.x = e.pageX;
        cursor.y = e.pageY;
    } 
    else {
        var de = document.documentElement;
        var b = document.body;
        cursor.x = e.clientX + 
            (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
        cursor.y = e.clientY + 
            (de.scrollTop || b.scrollTop) - (de.clientTop || 0);
    }
    return cursor;
}

function drawPoints(paper, graphcanvas_width, graphcanvas_height, dx, dy, dz, xlim, ylim, col, includeStroke) {
	
	if (!col) {
		col = "black";	
	}
	
	if (!xlim) {
		minx = getMin(dx) - MARGIN;
		maxx = getMax(dx) + MARGIN;
	} else {
		minx = xlim[0];
		maxx = xlim[1];	
	}
	
	if (!ylim) {
		miny = getMin(dy) - MARGIN;
		maxy = getMax(dy) + MARGIN;
	} else {
		miny = ylim[0];
		maxy = ylim[1];	
	}
	
	if (!dz || dz.length == 0) {
		dz = []
		for (i = 0; i < dx.length; i++) {
			dz[i] = 1;
		}	
	}

	offsetx = AXIS_SIZE;
	offsety = AXIS_SIZE;
	graphcanvas_width = graphcanvas_width - offsetx;
	graphcanvas_height = graphcanvas_height - offsety;
	
	var points = [];
	
	for (i = 0; i < dx.length; i++) {
		
		var p = convertToPoint(dx[i], dy[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
		circ = paper.circle(p[0], p[1], POINT_RADIUS * dz[i]);
		circ.attr({fill: col});
		circ.yValue = dy[i];// + "";
		circ.node.yValue = dy[i]; // Same as above.
		
		if (includeStroke) {
			circ.attr({"stroke-width":includeStroke});
		} else {
			circ.attr({"stroke-width":0});
		}
		
		points[i] = circ;
			
	}
	
	return points;
	
}

function drawAxis(paper, graphcanvas_width, graphcanvas_height, dx, dy, pch, xlim, ylim, lwd, col, breaksX, breaksY, breaklabX, breaklabY) {

	if (!pch) {
		pch = " ";	
	}
	
	if (!col) {
		col = "black";	
	}
	
	if (!lwd) {
		lwd = 1;	
	}
	
	if (!xlim) {
		minx = getMin(dx) - MARGIN;
		maxx = getMax(dx) + MARGIN;
	} else {
		minx = xlim[0];
		maxx = xlim[1];	
	}
	
	if (!ylim) {
		miny = getMin(dy) - MARGIN;
		maxy = getMax(dy) + MARGIN;
	} else {
		miny = ylim[0];
		maxy = ylim[1];	
	}
	
	offsetx = AXIS_SIZE;
	offsety = AXIS_SIZE;
	graphcanvas_width = graphcanvas_width - offsetx;
	graphcanvas_height = graphcanvas_height - offsety;

	var px_min = convertToPoint(minx, miny, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	var px_max = convertToPoint(minx, maxy, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	
	var py_min = convertToPoint(minx, miny, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	var py_max = convertToPoint(maxx, miny, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	
//	line_x = paper.path("M" + px_min[0] + " " + px_min[1] + "L" + px_max[0] + " " + px_max[1]);
//	line_x.attr({"stroke-width": 2});
//	line_y = paper.path("M" + py_min[0] + " " + py_min[1] + "L" + py_max[0] + " " + py_max[1]);
//	line_y.attr({"stroke-width": 2});
	
	linestring = "M" + px_max[0] + " " + px_max[1] + "L" + px_min[0] + " " + px_min[1] + "L" + py_max[0] + " " + py_max[1];
	axisline = paper.path(linestring);


	axisline.attr({"stroke-linejoin": "round"});

	axisline.attr({stroke: col});
	axisline.attr({"stroke-dasharray": pch});
	axisline.attr({"stroke-width": lwd});

	AXIS_LABEL_LENGTH = 5;
	AXIS_LABEL_TEXT_OFFSET = 7;
	DRAW_GRID_LINES_X = true;
	DRAW_GRID_LINES_Y = true;

	// If breaks are defined.
	if (breaksX) {
		for (i = 0; i < breaksX.length; i++) {
			// Y point for axis: py_min[1]
			
			var breakPoint = convertToPoint(breaksX[i], miny, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);			
			//document.write(breakPoint);
			
			breakline = paper.path("M" + breakPoint[0] + " " + breakPoint[1] + "L" + breakPoint[0] + " " + (breakPoint[1] + AXIS_LABEL_LENGTH));
			if (!breaklabX) {
				breaktext = paper.text(breakPoint[0], breakPoint[1] + AXIS_LABEL_LENGTH + AXIS_LABEL_TEXT_OFFSET, breaksX[i] + "")
			} else {
				breaktext = paper.text(breakPoint[0], breakPoint[1] + AXIS_LABEL_LENGTH + AXIS_LABEL_TEXT_OFFSET, breaklabX[i] + "")
			}
			
			if (DRAW_GRID_LINES_X == true) {
				gp = convertToPoint(breaksX[i], maxy, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
				gridline = paper.path("M" + breakPoint[0] + " " + breakPoint[1] + "L" + gp[0] + " " + gp[1]);
				gridline.attr({stroke: "gray"});
				gridline.attr({"stroke-dasharray": "- "});
			}

			
		}
	}
	
	// If breaks are defined.
	if (breaksY) {
		for (i = 0; i < breaksY.length; i++) {
			// Y point for axis: py_min[1]
			
			var breakPoint = convertToPoint(minx, breaksY[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);			
			//document.write(breakPoint);
			
			breakline = paper.path("M" + (breakPoint[0]-AXIS_LABEL_LENGTH) + " " + breakPoint[1] + "L" + breakPoint[0] + " " + breakPoint[1]);
			if(!breaklabY) {
				breaktext = paper.text(breakPoint[0] - AXIS_LABEL_LENGTH - AXIS_LABEL_TEXT_OFFSET, breakPoint[1], breaksY[i] + "")
			} else {
				breaktext = paper.text(breakPoint[0] - AXIS_LABEL_LENGTH - AXIS_LABEL_TEXT_OFFSET, breakPoint[1], breaklabY[i] + "")
			}

			if (DRAW_GRID_LINES_Y == true) {
				gp = convertToPoint(maxx, breaksY[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
				gridline = paper.path("M" + breakPoint[0] + " " + breakPoint[1] + "L" + gp[0] + " " + gp[1]);
				gridline.attr({stroke: "gray"});
				gridline.attr({"stroke-dasharray": "- "});
			}
			
		}
	}

	return this;
	
}

function drawLine(paper, graphcanvas_width, graphcanvas_height, dx, dy, pch, xlim, ylim, lwd, col) {

	if (!pch) {
		pch = " ";	
	}
	
	if (!col) {
		col = "black";	
	}
	
	if (!lwd) {
		lwd = 1;	
	}
	
	if (!xlim) {
		minx = getMin(dx) - MARGIN;
		maxx = getMax(dx) + MARGIN;
	} else {
		minx = xlim[0];
		maxx = xlim[1];	
	}
	
	if (!ylim) {
		miny = getMin(dy) - MARGIN;
		maxy = getMax(dy) + MARGIN;
	} else {
		miny = ylim[0];
		maxy = ylim[1];	
	}

	offsetx = AXIS_SIZE;
	offsety = AXIS_SIZE;
	graphcanvas_width = graphcanvas_width - offsetx;
	graphcanvas_height = graphcanvas_height - offsety;
	
	linestring = "M";

	for (i = 0; i < dx.length; i++) {
		
		var p = convertToPoint(dx[i], dy[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
		linestring = linestring + p[0] + " " + p[1];
		if (i != dx.length - 1) {
			linestring = linestring + "L";
		}
			
	}
	
	line = paper.path(linestring);
	//line.attr({stroke: \"" + LINE_COLOR + "\""});
	//line.attr({stroke: " + "red" + "\""});
	
	line.attr({stroke: col});
	line.attr({"stroke-dasharray": pch});
	line.attr({"stroke-width": lwd});

	
	return [line];
	
}

function bargraph(paper, graphcanvas_width, graphcanvas_height, values, xlim, ylim, col) {

	xvals = [];
	for (i = 0; i < values.length; i++) {
		xvals[i] = i+1;
	}
	
	if (!xlim) {
		minx = 0;
		maxx = xvals.length + 1;	
	} else {
		minx = xlim[0];
		maxx = xlim[1];	
	}
	
	if (!ylim) {
		miny = 0;
		maxy = getMax(values) + MARGIN;
	} else {
		miny = ylim[0];
		maxy = ylim[1];
	}
	
	if (!col) {
		col = "red";	
	}
	
	offsetx = AXIS_SIZE;
	offsety = AXIS_SIZE;
	graphcanvas_width = graphcanvas_width - offsetx;
	graphcanvas_height = graphcanvas_height - offsety;
	
	BAR_SEPARATION = 15;
	
	p1 = convertToPoint(1, 0, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	p2 = convertToPoint(2, 0, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
	BAR_HALF_WIDTH = ((p2[0] - p1[0]) / 2.0) - BAR_SEPARATION;
	//BAR_HALF_WIDTH = 0;
	
	bars = []
	
	for (i = 0; i < values.length; i++) {
	
	
		//document.write("<BR>" + xvals[i] + "<BR>");
		pTop = convertToPoint(xvals[i], values[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
		pBottom = convertToPoint(xvals[i], miny, minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
		ls = "M" + pTop[0] + " " + pTop[1] + "L" + pBottom[0] + " " + pBottom[1];
		//document.write(ls);
		//pth = paper.path("M" + (pBottom[0] - BAR_HALF_WIDTH) + " " + pBottom[1] + "L" + (pTop[0] + BAR_HALF_WIDTH) + " " + pTop[1]);
		//bar = paper.rect(pBottom[0] - BAR_HALF_WIDTH, pBottom[1], BAR_HALF_WIDTH * 2, pTop[1] - pBottom[1]);
		bar = paper.rect(pTop[0] - BAR_HALF_WIDTH, pTop[1], BAR_HALF_WIDTH * 2, pBottom[1] - pTop[1]);
		bar.attr({"stroke-width":0});
		bar.attr({fill:col});
		//bar.attr({"fill-opacity":0.5}); // useful!
		//document.write("<BR>" + (pTop[1] - pBottom[1]));
		
		//pTop[0] + BAR_HALF_WIDTH, pTop[1]);
		//bar.attr({fill: "red"});
		
	}
	
}

function netplot(paper, graphcanvas_width, graphcanvas_height, dx, dy, dz, neighs, nodecol, xlim, ylim) {

	if (!xlim) {
		minx = getMin(dx) - MARGIN;
		maxx = getMax(dx) + MARGIN;
	} else {
		minx = xlim[0];
		maxx = xlim[1];	
	}
	
	if (!ylim) {
		miny = getMin(dy) - MARGIN;
		maxy = getMax(dy) + MARGIN;
	} else {
		miny = ylim[0];
		maxy = ylim[1];	
	}
	
	if (!nodecol) {
		nodecol = "white";	
	}

	offsetx = AXIS_SIZE;
	offsety = AXIS_SIZE;
	graphcanvas_width = graphcanvas_width - offsetx;
	graphcanvas_height = graphcanvas_height - offsety;
			
	var points = []
	var pX = []
	var pY = []
	
	// Get coordinates...
	for (i = 0; i < dx.length; i++) {
		var p = convertToPoint(dx[i], dy[i], minx, maxx, miny, maxy, offsetx, offsety, graphcanvas_width, graphcanvas_height);
		pX[i] = p[0];
		pY[i] = p[1];
	}
	
	var edges = [];
	
	// Draw lines...
	for (i = 0; i < neighs.length; i++) {
		var j = 0;
		for (j = 0; j < neighs[i].length; j++) {
			edges[edges.length] = paper.path("M" + pX[i] + " " + pY[i] + "L" + pX[neighs[i][j]] + " " + pY[neighs[i][j]]);
			//edges[edges.length-1].attr({"stroke-dasharray": "- "});
			edges[edges.length-1].attr({"colour":"gray"});
			edges[edges.length-1].attr({"stroke-width":2});
		}
	}
	
	// Draw nodes...
	for (i = 0; i < dx.length; i++) {
		points[i] = paper.circle(pX[i], pY[i], dz[i]*POINT_RADIUS);
		points[i].attr({fill: nodecol});
	}

	return [points, edges];
		
}
