/**
	@file This file contains the constants, variables, and functions that
	server generic purposes for use in the Google Maps implementation on
	the RRP site.

	USES:

	USED BY:
		/maps/scripts/markers.php
		/maps/scripts/regions.php

	INCLUDED BY:
		/maps.php
 */

/*--------------------------------------------------------------------------*/
/**
	@brief This function searches an XML tree for nodes with a given tag
	name.  It then returns the text contained within the first node found.
	@param xml_doc XML document tree to search.
	@param tag XML node to find.
	@return Returns the text contained within the first XML node found.
 */
function GetNodeValue(xml_doc, tag) { /* {{{ */

	var text = '';			// text to be returned
	var tags = xml_doc.getElementsByTagName(tag);	// get array of nodes with given tag name

	// check to make sure there was at least one node found
	if (tags.length > 0) {
		if (tags.item(0).firstChild) {		// make sure that there is text to return
			text = tags.item(0).firstChild.nodeValue;	// get text
		}
	}

	// return text contained by node
	return text;
} /* }}} */

/*--------------------------------------------------------------------------*/
/**
	@brief This function searches an XML tree for nodes with a given tag
	name. It then returns the value of the requested attribute for the
	first node found.
	@param xml_doc XML document tree to search.
	@param tag XML node to find.
	@param attribute The attribute to return.
	@return The value of the requested attribute from the first node found.
 */
function GetNodeAttribute(xml_doc, tag, attribute) { /* {{{ */

	var value = '';		// value to be returned
	var tags = xml_doc.getElementsByTagName(tag);	// get array of nodes with given tag name

	// check to make sure there was at least one node found
	if (tags.length > 0) {
		value = tags.item(0).getAttribute(attribute);	// get attribute of first node found
	}

	// return value of attribute
	return value;
} /* }}} */

/****************************************************************************
 * FUNCTION:	distance
 *		PARAM point1:	GLatLng object; starting point
 *		PARAM point2:	GLatLng object; ending point
 *		RETURN:	float; distance between the two points
 *	This function returns the distance between the two given points.
****************************************************************************/
function distance(point1, point2) {

	// get x, y of first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());

	// get x, y of second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// return the distance between the two (standard distance formula)
	return Math.sqrt( Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2) );
}

/****************************************************************************
 * FUNCTION:	calculateSlope
 *		PARAM point1:	GLatLng object; first point of line
 *		PARAM point2:	GLatLng object; second point of line
 *		RETURN:	float; slope of line defined by the two given points
 *	This function computes the slope of the line define by the two given
 *	points.
****************************************************************************/
function calculateSlope(point1, point2) {

	// get x, y of first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());

	// get x, y of second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// return the slope of the line (standard slope formula)
	return ((y2 - y1) / (x2 - x1));
}

/****************************************************************************
 * FUNCTION:	calculateB
 *		PARAM x:	float; represents x in the equation of the line
 *		PARAM y:	float; represents y in the equation of the line
 *		PARAM m:	float; represents m (slope) in the equation of the line
 *		RETURN:	float; b from the equation of the line defined by x, y, and m
 *	This function calculates b for the equation of the line defined by x, y, and m
****************************************************************************/
function calculateB(x, y, m) {

	// return b (standard equation of line: y = mx + b; solve for b)
	return parseFloat(y - (m * x));
}

/****************************************************************************
 * FUNCTION:	determineIfSolveForY
 *		PARAM point1:	GLatLng object; first point of line
 *		PARAM point2:	GLatLng object; second point of line
 *		PARAM m:	float; slope of line
 *		PARAM b:	float; b in equation of line
 *		PARAM pan_factor:	float; increment value for pan move
 *		RETURN:	bool;	If true, we want to solve for y and increment x in the
 *						equation of a line.  If false, we want to solve
 *						for x and increment y in the equation of a line.
 *	This function determines if the equation of a line should be solved for
 *	y by incrementing x by pan_factor, or if an equation of a line should
 *	be solved for x by incrementing y by pan_factor.  If solving for y, the
 *	difference between y values cannot be greater than pan_factor.  If it is,
 *	then we want to solve for x instead of y.
****************************************************************************/
function determineIfSolveForY(point1, point2, m, b, pan_factor) {

	// We are going to increment x1 and y1 by pan_factor and determine
	// their corresponding x and y coordinates.  We will then check
	// to see if the difference between x1 and y3's x coordinate is 
	// greater than pan_factor, if it is, then we will need to increment
	// x instead of y each time.
	
	// get x, y for first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());
	
	// get x, y for second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// new x, y coordinates
	var x3 = 0;
	var y3 = 0;
	
	// is point1 to the left of point2?...
	if (x1 < x2) {
		// ... if so, we need to move to the righ.
		x3 = parseFloat(x1 + pan_factor);
	} else {
		// ... else we need to move to the left
		x3 = parseFloat(x1 - pan_factor);
	}

	// is point1 below point2?...
	if (y1 < y2) {
		// ... if so, we need to move up
		y3 = parseFloat(y1 + pan_factor);
	} else {
		// ... else we need to move down
		y3 = parseFloat(y1 - pan_factor);
	}

	var x_solved = parseFloat((y3 - b) / m);	// Find corresponding x coordinate
	var y_solved = parseFloat((m * x3) + b);	// Find corresponding y coordinate

	var bit_solve_for_y = false;	// return value, initialize to false

	// calculate the difference in y and x values
	var x_val_diff = Math.abs(x_solved - x1);	// we incremented y
	var y_val_diff = Math.abs(y_solved - y1);	// we incremented x

	// if x value difference is greater than pan_factor,
	// we want to increment X by pan_factor and solve for y
	if (x_val_diff > pan_factor) {
		bit_solve_for_y = true;
	} else {
		bit_solve_for_y = false;
	}

	// return decision
	return bit_solve_for_y;
}

/*--------------------------------------------------------------------------*/
/**
	@brief This function removes all children from the given node.
	@param node The node to remove child nodes from.

	@note The removal algorithm follows the best practices method of
	removing the children of all child nodes first.  This helps to
	avoid memory leaks.
 */
function RemoveChildNodes(node) { /* {{{ */

	while (node.hasChildNodes()) {
		RemoveChildNodes(node.lastChild);
		node.removeChild(node.lastChild);
	}

	return;
} /* }}} */

/*--------------------------------------------------------------------------*/
/**
	@brief This function creates and returns a zoom level object (min, max)
	from the given parameters.  If no parameters are given, then it uses
	the minimum and maximum zoom levels of the map.
	@param min Minimum zoom level.
	@param max Maximum zoom level.
	@return Returns a zoom level object.
 */
function CreateZoomLevelObject(min, max) { /* {{{ */

	// check if min was given
	if (min == undefined) {
		// if not, use default
		min = MIN_ZOOM_LEVEL;
	}

	// check if max was given
	if (max == undefined) {
		// if not, use default
		max = MAX_ZOOM_LEVEL;
	}

	// create object
	zoom = new Object();
	zoom.min = min;
	zoom.max = max;

	return zoom;
} /* }}} */

/*--------------------------------------------------------------------------*/
/**
	@brief This function gets the XML document from an XmlHttpRequest
	response object.
	@param response The reponse object to get the XML document from.
	@return Returns an XML document root node, or NULL if there was an
	error or no document.
 */
function GetXMLDocument(response) { /* {{{ */

	var use_response_stream = false; // whether or not to use responseStream instead of responseXML
	var xml_doc = null; // XML document to be returned

	// check if responseXML is non-null and not a documentElement
	if (response.responseXML) {
		
		if (!response.responseXML.documentElement) {

			// if so, use response stream instead
			use_response_stream = true;
		}
	}
	// else response XML is null
	else {

		// if responseXML is null, use response stream instead
		use_response_stream = true;
	}

	// check if we are suppose to use a response stream
	if (true == use_response_stream) {

		// if so, check if a response stream is available
		if (response.responseStream) {

			// if so, use it instead
			response.responseXML.load(response.responseStream);

		}
	}

	// set referece to XML document in the response
	if (response.responseXML && response.responseXML.documentElement) {
		xml_doc = response.responseXML.documentElement;
	}

	// return XML document reference
	return xml_doc;
} /* }}} */

/****************************************************************************
 * FUNCTION:	distance
 *		PARAM point1:	GLatLng object; starting point
 *		PARAM point2:	GLatLng object; ending point
 *		RETURN:	float; distance between the two points
 *	This function returns the distance between the two given points.
****************************************************************************/
function distance(point1, point2) {

	// get x, y of first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());

	// get x, y of second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// return the distance between the two (standard distance formula)
	return Math.sqrt( Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2) );
}

/****************************************************************************
 * FUNCTION:	calculateSlope
 *		PARAM point1:	GLatLng object; first point of line
 *		PARAM point2:	GLatLng object; second point of line
 *		RETURN:	float; slope of line defined by the two given points
 *	This function computes the slope of the line define by the two given
 *	points.
****************************************************************************/
function calculateSlope(point1, point2) {

	// get x, y of first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());

	// get x, y of second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// return the slope of the line (standard slope formula)
	return ((y2 - y1) / (x2 - x1));
}

/****************************************************************************
 * FUNCTION:	calculateB
 *		PARAM x:	float; represents x in the equation of the line
 *		PARAM y:	float; represents y in the equation of the line
 *		PARAM m:	float; represents m (slope) in the equation of the line
 *		RETURN:	float; b from the equation of the line defined by x, y, and m
 *	This function calculates b for the equation of the line defined by x, y, and m
****************************************************************************/
function calculateB(x, y, m) {

	// return b (standard equation of line: y = mx + b; solve for b)
	return parseFloat(y - (m * x));
}

/****************************************************************************
 * FUNCTION:	determineIfSolveForY
 *		PARAM point1:	GLatLng object; first point of line
 *		PARAM point2:	GLatLng object; second point of line
 *		PARAM m:	float; slope of line
 *		PARAM b:	float; b in equation of line
 *		PARAM pan_factor:	float; increment value for pan move
 *		RETURN:	bool;	If true, we want to solve for y and increment x in the
 *						equation of a line.  If false, we want to solve
 *						for x and increment y in the equation of a line.
 *	This function determines if the equation of a line should be solved for
 *	y by incrementing x by pan_factor, or if an equation of a line should
 *	be solved for x by incrementing y by pan_factor.  If solving for y, the
 *	difference between y values cannot be greater than pan_factor.  If it is,
 *	then we want to solve for x instead of y.
****************************************************************************/
function determineIfSolveForY(point1, point2, m, b, pan_factor) {

	// We are going to increment x1 and y1 by pan_factor and determine
	// their corresponding x and y coordinates.  We will then check
	// to see if the difference between x1 and y3's x coordinate is 
	// greater than pan_factor, if it is, then we will need to increment
	// x instead of y each time.
	
	// get x, y for first point
	x1 = parseFloat(point1.lng());
	y1 = parseFloat(point1.lat());
	
	// get x, y for second point
	x2 = parseFloat(point2.lng());
	y2 = parseFloat(point2.lat());

	// new x, y coordinates
	var x3 = 0;
	var y3 = 0;
	
	// is point1 to the left of point2?...
	if (x1 < x2) {
		// ... if so, we need to move to the righ.
		x3 = parseFloat(x1 + pan_factor);
	} else {
		// ... else we need to move to the left
		x3 = parseFloat(x1 - pan_factor);
	}

	// is point1 below point2?...
	if (y1 < y2) {
		// ... if so, we need to move up
		y3 = parseFloat(y1 + pan_factor);
	} else {
		// ... else we need to move down
		y3 = parseFloat(y1 - pan_factor);
	}

	var x_solved = parseFloat((y3 - b) / m);	// Find corresponding x coordinate
	var y_solved = parseFloat((m * x3) + b);	// Find corresponding y coordinate

	var bit_solve_for_y = false;	// return value, initialize to false

	// calculate the difference in y and x values
	var x_val_diff = Math.abs(x_solved - x1);	// we incremented y
	var y_val_diff = Math.abs(y_solved - y1);	// we incremented x

	// if x value difference is greater than pan_factor,
	// we want to increment X by pan_factor and solve for y
	if (x_val_diff > pan_factor) {
		bit_solve_for_y = true;
	} else {
		bit_solve_for_y = false;
	}

	// return decision
	return bit_solve_for_y;
}


