/*
 *	Creates a table dynamically from the given xml document object
 *  @dependant on: jquery-1.2.1.js, jquery.tablesorter.js
 *	@param xmlDoc : the xml document object to extract data from
 *  @param sRowTag: Row XML tag
 *  @param sColumnTag: Column XML tag
 *	@param sTargetEl: element to append created table
 *  @param sTableID : id of dynamically created table element
 *  @param sOptionList : List of optional params, see below:
 *  Option list can contain
 *    #FILTER=batter,bowler,fielder comma seperated list if values to filter on.
 *    #SECOND_SELECT_LIST=batter,bowler,fielder   comma seperated list if values to filter on. If Second filter present.
 *    #FILTER_ATTRIBUTE=player_type   required in addition to above.  the XML row attribute to check against.
 *    #SPLIT=token                    for chattel name, splits over 2 lines, cuts at token.
 *    #ALIGN=boolean                  if true we look for a global var called g_sAlignOverride with align values.
 *    #ONCLICK=string                 pass in the javascript for the onclick.
 *    #TOTALS=boolean                 if true, 2nd row in XML is used for totals.
 *    #NORANK=boolean                 if true the first column will use XML data, not loop value.
 *    #PREFIX=string                  a string to prefix the first column.
 *    #BOLDUSER=boolean               if true,bolds row displaying user's team
 */

function createTable(xmlDoc, sRowTag, sColumnTag, sTargetEl, sTableID, sOptionList, isSorted, arrayAlign)
{
	// loading image
	$("#" + sTargetEl).html("<div class=\"text-center\"><img src=\""+ g_sBaseLocation +"/images/imgLoading.gif\" alt=\"\"><\div>");

	if (xmlDoc.documentElement && xmlDoc.documentElement.tagName && xmlDoc.documentElement.tagName.toUpperCase() == "HTML")
	{
		$("#" + sTargetEl).html("An error has occurred. Your browser may not be compatible with this site.");
		return;
	}

	var xmlRows = xmlDoc.getElementsByTagName(sRowTag);
	var sAlign = new Array(xmlRows[0].childNodes.length); // will contain the CSS align types
	var sOutTable = "<table id=\"" + sTableID + "\" class=\"tablesorter\"><thead><tr>";

	// make all alignment right by default
	// unless specified in the g_sAlignOverride option
	for ( var i = 0; i < xmlRows[0].childNodes.length; i++ )
	{
		sAlign[i] = "text-right";
	}


	try
	{
		for (var i = 0; i < arrayAlign.length; i++)
		{
			sAlign[i] = arrayAlign[i];
		}
	}
	catch(err)
	{
		for ( var i = 0; i < xmlRows[0].childNodes.length; i++ )
		{
			sAlign[i] = "text-right";
		}
	}


	/*
	 * This section just does the column headings
	 * which are in the first row of data [0]
	 */
	var xmlColumns = xmlRows[0].getElementsByTagName(sColumnTag);
	var sTtip = ""; // Tooltip

	for (var i = 0; i < xmlColumns.length; i++)
	{
		// if there are no tooltips show nothing
		sTtip = xmlColumns[i].getAttribute("ttip");

		if (sTtip === null)
		{
			sTtip = "";
		}

		var sCellData = "";

		try
		{
			if (g_xlationTable != undefined) // if g_xlationTable is undefined, throws an error
			{
				sCellData = "<th class=\"" + sAlign[i] + "\" title=\"" + g_xlationTable.get(sTtip + "_LONG") + "\" nowrap>";
				sCellData += g_xlationTable.get(xmlColumns[i].firstChild.nodeValue + "_SHORT");
			}
		}
		catch(err)
		{
			sCellData = "<th class=\"" + sAlign[i] + "\" title=\"" + sTtip + "\" nowrap>";
			sCellData += xmlColumns[i].firstChild.nodeValue;
		}

		sCellData += "</th>";
		sOutTable += sCellData;
	}

	sOutTable += "</tr></thead>";

	/*
	 * This section does a totals row
	 * if the #TOTALS is true
	 */
	if (haveOption(sOptionList, "#TOTALS") && xmlRows.length > 1)
	{
		var xmlColumns = xmlRows[1].getElementsByTagName(sColumnTag);

		sOutTable += "<tfoot><tr>";

		for (var i = 0; i < xmlColumns.length; i++)
		{
			var sCellData = "";

			sCellData = "<th class=\"" + sAlign[i] + "\">";
			sCellData += xmlColumns[i].firstChild.nodeValue;
			sCellData += "</th>";
			sOutTable += sCellData;
		}

		sOutTable += "</tr></thead>";
	}

	/*
	 * This section builds the main table
	 */
	var iRowCount = 0;
	var sPrefix = "";

	if (haveOption(sOptionList, "#PREFIX"))
	{
		sPrefix = getOption(sOptionList, "#PREFIX", "|");
	}

	sOutTable += "<tbody>";

	for (var i = 1; i < xmlRows.length; i++)
	{

		if (haveOption(sOptionList, "#TOTALS") && i == 1)
		{
			continue; // skip the totals row.
		}

		sCellData = "";

		// get array of all the columns in this row
		xmlColumns = xmlRows[i].getElementsByTagName(sColumnTag);

		// check if this page uses filtering
		// if isRenderRow ends up false, we skip this row.
		var isRenderRow = !haveOption(sOptionList, "#FILTER");  // if filter not set, make this = true
		var sFilterAttr = getOption( sOptionList, "#FILTER_ATTRIBUTE", "|");
		if (haveOption(sOptionList, "#FILTER") &&  getOption(
																												 getOption( sOptionList, "#FILTER", "|")     // gets the filter values passed into the script
																												 ,xmlRows[i].getAttribute(sFilterAttr), ",") // checks (above) against the value from the XML
		)
		{
			isRenderRow = true;
		}


		//if second select list is present
		// check if this page uses second filter
		// if isRenderRow2 ends up false, we skip this row.
		var isRenderRow2 = !haveOption(sOptionList, "#SECOND_SELECT_LIST");  // if second_select_list not set, make this = true
		sFilterAttr = getOption( sOptionList, "#SECOND_SELECT_LIST_ATTRIBUTE", "|");
		if (haveOption(sOptionList, "#SECOND_SELECT_LIST") &&  getOption(
																											 getOption( sOptionList, "#SECOND_SELECT_LIST", "|")     // gets the filter values passed into the script
																											 ,xmlRows[i].getAttribute(sFilterAttr), ",") // checks (above) against the value from the XML
		)
		{
			isRenderRow2 = true;
		}

		// output a table row here
		if(isRenderRow && isRenderRow2)
		{
			iRowCount++;
			if (haveOption(sOptionList, "#ONCLICK"))
			{
				sCellData = "<tr style=\"cursor: pointer\" id=\"" + xmlRows[i].getAttribute("id") + "\"" + getOption(sOptionList, "#ONCLICK", "|") + ">";
			}
			else
			{
				sCellData = "<tr id=\"" + xmlRows[i].getAttribute("id") +"\">";
			}

			// loop thru the columns in this row
			for (var j = 0; j < xmlColumns.length; j++)
			{
				sCellData += "<td class=\"" + sAlign[j] + "\">";

				if (j == 0 )
				{
					if (haveOption(sOptionList, "#NORANK"))
					{
						var sHidSort = "<span style=\"display:none;\">" + getGuaranteedLength(xmlColumns[j].firstChild.nodeValue) + "</span>";
						sCellData += sHidSort + sPrefix + xmlColumns[j].firstChild.nodeValue + "</td>";
						continue;
					}
					else
					{
						// this section uses iRowCount for the ranking value instead of the XML data

						var sHidSort = "<span style=\"display:none;\">" + getGuaranteedLength(iRowCount) + "</span>";

						sCellData += sHidSort + sPrefix + iRowCount + "</td>";
						continue;
					}
				}

				// this looks for a '#' placeholder used in the chattel name display
				var sTempText = addCommas(xmlColumns[j].firstChild.nodeValue);

				if (haveOption(sOptionList, "#SPLIT") && sTempText.indexOf(getOption( sOptionList, "#SPLIT", "|")) != -1)
				{
					var iSubEnd = sTempText.length;                         // Full Name length
					var iSubStart = sTempText.indexOf(getOption( sOptionList, "#SPLIT", "|")) + 1;             // Start Position of Surname
					var sSurname = sTempText.substring(iSubStart, iSubEnd); // Extracted Surname

					// Replace the old surname with new bold one
					var sTempText = sTempText.replace("#" + sSurname, "<h5>" + sSurname + "</h5>");

					// includes a hidden span for sorting purposes
					sCellData +=  "<span style=\"display:none\">" + sSurname + "</span>" + sTempText;
				}
				else
				{
					sCellData += sTempText;
				}

				sCellData += "</td>";
			}

			sCellData += "</tr>";
		}

		sOutTable += sCellData;
	}

	// get the column headings again to use for length calculations
	xmlColumns = xmlRows[0].getElementsByTagName(sColumnTag);

	// if no rows (apart from the heading), display this message
	if (iRowCount == 0)
	{
		sOutTable += "<tr><td id=\"noData\" colspan=\"" + xmlColumns.length + "\">No data found</td></tr>";
	}

	sOutTable += "</tbody>";
	sOutTable += "</table>";

	$("#" + sTargetEl).html(sOutTable);

	$("th > span").before("<br/>"); // set the style of secondary header
	$("#noData").css({ background: "#F0F0F0"});

	//bold user's team row
	if (haveOption(sOptionList, "#BOLDUSER") && (g_sUSquad !== undefined))
	{
		$("#" + g_sUSquad).addClass("bold");
	}

	// may need option later to switch on pager if not used on all pages.
	showPager(); // display pager

	return iRowCount;
}

/*
 *  Adds and shows a pager after any table with a .tablesorter class
 *  Number of rows displayed in one page can be set.
 *  @dependant on: jquery-1.2.1.js, jquery.tablesorter.js
 */
function showPager(){
	$('table.tablesorter').each(function(){
		var iCurrentPage = 0;
		var iNumPerPage = 20; //set number of rows visible in a single page.
		var iNumRows = 0;
		var tablePage = $(this);
		var divPager = $("<div class=\"pager\"></div>");
		var divPageNums = $("<span id=\"pageNums\"></span>"); //will display the current batch of pages.
		var divHiddenCurrentNo = $("<div id=\"hidCurrPage\">" + iCurrentPage + "</div>"); //stores the current active page number.
		var spanMoreLeft = $("<span style=\"display:inline;\" id=\"moreLeftPages\">... </span>");
		var spanMoreRight = $("<span style=\"display:inline;\" id=\"moreRightPages\"> ...</span>");
		divHiddenCurrentNo.insertBefore(tablePage).hide();

		iNumRows = tablePage.find("tbody tr").length;
		var iNumPages = Math.ceil(iNumRows / iNumPerPage);

		tablePage.bind("repaginate", function(){
			tablePage.find("tbody tr").show()
			.slice(0,iCurrentPage * iNumPerPage)
			.hide()
			.end()
			.slice((iCurrentPage + 1) * iNumPerPage )
			.hide()
			.end();

			var iLowestNum = parseInt($("#pageNums").children(":first").text());
			var iHighestNum = parseInt($("#pageNums").children(":last").text());
			//CODE TO SHOW AND HIDE <<PREV AND NEXT>> BUTTONS
			if(iLowestNum === 1){
				$("#prevPage").hide();
				spanMoreLeft.hide();
			}else{
				$("#prevPage").show();
				spanMoreLeft.show();
				(divPageNums).before(spanMoreLeft);
			}

			if((iHighestNum + 1) >= iNumPages){
				$("#nextPage").hide();
				spanMoreRight.hide();
			}else{
				$("#nextPage").show();
				spanMoreRight.show();
				(divPageNums).after(spanMoreRight);
			}
		});

		//RUNS ONLY WHEN THE SCRIPT LOADS FIRST
		var iFirstRun;
		if (iNumPages > 10){
			iFirstRun = 10;
		}else{
			iFirstRun = iNumPages;
		}

		for (var iPageNo = 0; iPageNo < iFirstRun; iPageNo++){
			$("<span id=\"pg" + iPageNo + "\"class=\"page-number\">" + (iPageNo + 1) + "</span>")
			.bind("click", {"newPage": iPageNo}, function(event){
				iCurrentPage = event.data["newPage"];
				$("#hidCurrPage").html(event.data["newPage"]);
				tablePage.trigger("repaginate");
				$(this).addClass("active").siblings().removeClass("active");
			})
			.appendTo(divPageNums).addClass("pointer");
		}
		divPageNums.find("span.page-number:first").addClass("active");

		//GOT TO FIRST PAGE
		$("<span id=\"firstPage\">first | </span>")
		.bind("click", {"firstPage": 0}, function(event){
			iCurrentPage = event.data["firstPage"];
			$("#pageNums").empty();
			for (var iPageNo = 0; iPageNo < 10; iPageNo++){
				if (iPageNo < iNumPages){
					$("<span id=\"pg" + iPageNo + "\" class=\"page-number\">" + (iPageNo + 1) + "</span>")
					.bind("click", {"newPage": iPageNo}, function(event){
						iCurrentPage = event.data["newPage"];
						$("#hidCurrPage").html(event.data["newPage"]);
						$(this).addClass("active").siblings().removeClass("active");
						tablePage.trigger("repaginate");
					})
					.appendTo(divPageNums).addClass("pointer");
				}
			}
			$("#hidCurrPage").html("0");
			tablePage.trigger("repaginate");
			$("#pg" + iCurrentPage).addClass("active").siblings().removeClass("active");
		})
		.appendTo(divPager).addClass("pointer").css("color","black");

		//GO TO PREV TEN PAGES
		$("<span id=\"prevPage\">&laquo;prev10</span>").css("padding-right", "5px")
		.bind("click", function(event){
			var iLowestNum = parseInt($("#pageNums").children(":first").text());
			//var highestNumber = parseInt($("#pageNums").children(":last").text());
			if(iLowestNum != 1) {
				$("#pageNums").empty();

				for (var iPageNo = (iLowestNum - 10 ); iPageNo < iLowestNum; iPageNo++){
					if (iPageNo >= 0){
						$("<span id=\"pg" + iPageNo + "\" class=\"page-number\">" + (iPageNo + 1) + "</span>")
						.bind("click", {"newPage": (iPageNo)}, function(event){
							iCurrentPage = event.data["newPage"];
							//iCurrentPage = iLowestNum;
							$("#hidCurrPage").html(event.data["newPage"]);
							$(this).addClass("active").siblings().removeClass("active");
							tablePage.trigger("repaginate");
						})
						.appendTo(divPageNums).addClass("pointer");
					}
				}
				$("#pageNums").children(":last").click().addClass("active").siblings().removeClass("active");
			}
		})
		.appendTo(divPager).addClass("pointer").css("color","black");

		divPageNums.appendTo(divPager);//show page numbers


		//GO TO NEXT TEN PAGES
		$("<span id=\"nextPage\">next10&raquo;</span>").css("padding-left","5px")
		.bind("click", function(event){
			var iHighestNum = parseInt($("#pageNums").children(":last").text());
			//var iLowestNum = parseInt($("#pageNums").children(":first").text());
			if((iHighestNum + 1)  < iNumPages){
				$("#pageNums").empty();

				for (var iPageNo = iHighestNum; iPageNo < (iHighestNum + 10); iPageNo++){
					if (iPageNo < iNumPages){
						$("<span id=\"pg" + iPageNo + "\" class=\"page-number\">" + (iPageNo) + "</span>")
						 .bind("click", {"newPage": iPageNo}, function(event){
							iCurrentPage = event.data["newPage"];
							$("#hidCurrPage").html(event.data["newPage"]);
							$(this).addClass("active").siblings().removeClass("active");
							tablePage.trigger("repaginate");
						 })
						 .appendTo(divPageNums).addClass("pointer");
					}
				}
				 $("#pageNums").children(":first").click().addClass("active").siblings().removeClass("active");
			}
		})
		.appendTo(divPager).addClass("pointer").css("color","black");

		//GO TO LAST PAGE
		$("<span id=\"Page\"> | last</span>")
		.bind("click", {"lastPage": iNumPages - 1}, function(event){
			iCurrentPage = event.data["lastPage"];
			var iHighestNum = parseInt($("#pageNums").children(":last").text());
			if((iHighestNum + 1)  <= iNumPages){
				$("#pageNums").empty();
				for (var iPageNo = (iNumPages - 10); iPageNo < iNumPages; iPageNo++){
					if (iPageNo <= iNumPages){
						$("<span id=\"pg" + iPageNo + "\" class=\"page-number\">" + (iPageNo) + "</span>")
						.bind("click", {"newPage": iPageNo}, function(event){
							iCurrentPage = event.data["newPage"];
							$("#hidCurrPage").html(event.data["newPage"]);
							$(this).addClass("active").siblings().removeClass("active");
							tablePage.trigger("repaginate");
						})
						.appendTo(divPageNums).addClass("pointer");
					}
				}
			}

			$("#hidCurrPage").html(iNumPages - 1);
			tablePage.trigger("repaginate");
			$("#pg" + iCurrentPage).addClass("active").siblings().removeClass("active");
		})
		.appendTo(divPager).addClass("pointer").css("color","black");

		if (iNumRows > iNumPerPage){// only show pager if rows greater than 20
			divHiddenCurrentNo.insertAfter(tablePage).hide();
			divPager.insertAfter(tablePage);
		}
		tablePage.trigger("repaginate");
	});
}

/*
 *  Takes a pipe seperated param=value string and searches for a param.
 *  If param found, returns true.
 *
 *  @param sOptionList  list of options to search.
 *  @param sKey         param to search for.
 *  @return             boolean found
 */
function haveOption(sOptionList, sKey)
{
	var isFound = false;

	try
	{
		if (sOptionList.indexOf(sKey) != -1)
		{
			isFound = true;
		}
	}
	catch(err)
	{
		isFound = false;
	}

	return isFound;
}

/*
 *  Takes a pipe seperated param=value string and searches for a param.
 *  If found, returns the value .
 *
 *  @param sOptionList  list of options to search.
 *  @param sKey         param to search for.
 *  @return             string value found.
 */
function getOption(sOptionList, sKey, sToken)
{
	var sValueFound = "";

	try
	{
		if (sOptionList.indexOf(sKey) != -1)
		{
			var iKeyPos = sOptionList.indexOf(sKey);
			var iCutStart = sOptionList.indexOf("=", iKeyPos ) + 1;
			var iCutEnd = sOptionList.indexOf(sToken, iCutStart );

			if (iCutEnd === -1)
			{
				iCutEnd = sOptionList.length;
			}

			sValueFound = $.trim(sOptionList.substring(iCutStart, iCutEnd));
		}
	}
	catch(err)
	{
		sValueFound = "";
	}

	return sValueFound;
}

/**
 * Return a String with at least 4 characters.
 * This is designed to make strings representing numbers sortable.
 * For example, the string "3" will return "0003"
 * For example, the string "23" will return "0023"
 */
function getGuaranteedLength(sIn)
{
	var iLen = 4;

	while(sIn.length < iLen)
	{
		sIn = "0" + sIn;
	}

	return sIn;
}
