dataCache = { };
dataQueue = new Array();

function initTableLoad(tableElementId, options) {
	var cellDetails = options["cellDetails"];
	if (cellDetails == undefined) {
		alert("cellDetails undefined for " + tableElementId);
	}
	var dataSource = options["dataSource"];
	if (dataSource != undefined) {
		setTableInformation(tableElementId, cellDetails.length, "Loading...");
		
		dataQueue.push({tableElementId: tableElementId, options: options});
		
		if (dataQueue.length == 1) {
			loadNextInQueue();
		}
	} else {
		onTableDataLoaded(tableElementId, options, [ ]);
	}
}

function loadNextInQueue() {
	if (dataQueue.length < 1)
		return;
	
	var o = dataQueue[0];
	var tableElementId = o["tableElementId"];
	var options = o["options"];
	var dataSource = options["dataSource"];
	
	dataSource(function(data) {
		if (data.sorted) {
			onTableDataLoaded(tableElementId, options, data.sorted);
		} else {
			onTableDataLoaded(tableElementId, options, data);
		}
	});
}

function setTableInformation(tableElementId, colspan, text) {
	hidePagingElements(tableElementId);
	dwr.util.removeAllRows(tableElementId);

	var tr = document.createElement("tr");
	var td = document.createElement("td");
	td.colSpan = colspan;
	td.innerHTML = text;
	tr.appendChild(td);
	$(tableElementId).appendChild(tr);
}

function reloadTableData(tableElementId) {
	var dataStore = dataCache[tableElementId];
	var dataSource = dataStore["dataSource"];
	
	dataSource(function(data) {
		if (data.sorted) {
			onTableDataReLoaded(tableElementId, data.sorted);
		} else {
			onTableDataReLoaded(tableElementId, data);
		}
	});
}

function onTableDataLoaded(tableElementId, options, data) {
	var perPage = options["perPage"] || 0;
	var cellDetails = options["cellDetails"];
	var dataSource = options["dataSource"];
	var rowHandler = options["rowHandler"] || function(element, dataRow) { element.className += "_nohov"; return element; };
	var onLoaded = options["onLoaded"];
	var additionalDataHandler = options["additionalDataHandler"];
	
	var dataStore = { };
	dataStore["dataSource"] = dataSource;
	dataStore["sortedBy"] = -1;
	dataStore["sortedByReverse"] = false;
	dataStore["page"] = 1;
	dataStore["perPage"] = perPage;
	dataStore["rowHandler"] = rowHandler;
	dataStore["additionalDataHandler"] = additionalDataHandler;

	var cellFuncs = [];
	var cellIds = [];
	var cellStyles = [];
	var columnTypes = new Array(cellDetails.length);
	for (var i = 0; i < cellDetails.length; i++) {
		columnTypes[i] = cellDetails[i].type;
		if (!cellDetails[i].hidden) {
			cellIds.push(i);
			cellStyles.push(cellDetails[i].style || "");
			cellFuncs.push(function(displayData, options) {
				var cellNum = cellIds[(options["cellNum"] + 1)];
				if (cellNum == -1) {
					return "";
				}
				
				var result = displayData[cellNum];
				var type = columnTypes[cellNum];
				
				switch(type) {
				case "position" : result += ".";
					break;
				case "percent" : result += "%";
					break;
				case "time" : result += " <small>mins</small>";
					break;
				case "number" : result = formatNumberWithCommas(result);
					break;
				case "rnumber" : result = formatNumberWithCommas(result);
					break;
				case "date" : result = result.getDate() + "/" + (result.getMonth() + 1) + "/" + result.getFullYear();
					break;
				case "month" : result = (result.getMonth() + 1) + "/" + result.getFullYear();
					break;
				}
				
				return result;
			});
		}
	}
	dataStore["cellFuncs"] = cellFuncs;
	dataStore["columnTypes"] = columnTypes;
	dataStore["cellStyles"] = cellStyles;
	dataStore["cellDetails"] = cellDetails;
	dataCache[tableElementId] = dataStore;
	
	setupTableData(tableElementId, data);
	drawTable(tableElementId);
	
	dataQueue.shift();
	loadNextInQueue();
	
	if (onLoaded != undefined && onLoaded != null) {
		onLoaded();
	}
}

function onTableDataReLoaded(tableElementId, data) {
	setupTableData(tableElementId, data);
	drawTable(tableElementId);
}

function addTableRow(tableElementId, data) {
	var dataStore = dataCache[tableElementId];
	var perPage = dataStore["perPage"];
	var cellDetails = dataStore["cellDetails"];
	var convertedData = dataStore["data"];
	if (perPage < 1) {
		dataStore["maxPage"] = 1;
	} else {
		dataStore["maxPage"] = Math.floor((convertedData.length) / perPage) + 1;
	}
	
	// convert data using cellfuncs
	var dataRow = new Array(cellDetails.length);
	for (var j = 0; j < cellDetails.length; j++) {
		var cf = cellDetails[j].func;
		var type = cellDetails[j].type;
		var output = cf(data);
		if (type == "position") {
			output = (convertedData.length + 1);
		}
		dataRow[j] = output;
	}
	convertedData.push(dataRow);
	
	dataStore["data"] = convertedData;
	dataCache[tableElementId] = dataStore;
	
	drawTable(tableElementId);
}

function findTableRow(tableElementId, func) {
	var dataStore = dataCache[tableElementId];
	var convertedData = dataStore["data"];
	
	for (var i = 0; i < convertedData.length; i++) {
		if (func(convertedData[i])) {
			return i;
		}
	}
	
	return -1;
}

function removeTableRow(tableElementId, rowId) {
	var dataStore = dataCache[tableElementId];
	var convertedData = dataStore["data"];
	
	convertedData.splice(rowId, 1);
	
	dataStore["data"] = convertedData;
	dataCache[tableElementId] = dataStore;
	
	drawTable(tableElementId);
}

function setupTableData(tableElementId, data) {
	var dataStore = dataCache[tableElementId];
	var perPage = dataStore["perPage"];
	var cellDetails = dataStore["cellDetails"];
	if (perPage < 1) {
		dataStore["maxPage"] = 1;
	} else {
		dataStore["maxPage"] = (data.length == 0) ? 1 : Math.floor((data.length - 1) / perPage) + 1;
	}
	
	// convert data using cellfuncs
	var convertedData = [ ];
	for (var i = 0; i < data.length; i++) {
		var dataRow = new Array(cellDetails.length);
		for (var j = 0; j < cellDetails.length; j++) {
			var cf = cellDetails[j].func;
			var type = cellDetails[j].type;
			var output = cf(data[i]);
			if (type == "position") {
				output = (i + 1);
			}
			dataRow[j] = output;
		}
		convertedData.push(dataRow);
	}
	dataStore["data"] = convertedData;
	
	dataCache[tableElementId] = dataStore;
}

function formatNumberWithCommas(num) {
	var numString = new String(Math.abs(num));
	if (num >= 1000 || num <= -1000) {
		pos = numString.length - 3;
		while (pos >= 1) {
			numString = numString.substring(0,pos) + "," + numString.substring(pos,numString.length)
			pos -= 3;
		}
	}
	if (num < 0) {
		numString = "-" + numString;
	}
	return numString;
}

function drawTable(tableElementId) {
	var dataStore = dataCache[tableElementId];
	var perPage = dataStore["perPage"];
	var rawData = dataStore["data"];
	var additionalDataHandler = dataStore["additionalDataHandler"];
	
	var displayData;
	
	if (dataStore["page"] == -1 || perPage < 1) {
		displayData = rawData;
	} else {
		var startItem = perPage * (dataStore["page"] - 1);
		var endItem = startItem + perPage;
		displayData = rawData.slice(startItem, endItem);
	}
	
	if (additionalDataHandler != undefined && additionalDataHandler != null) {
		displayData = additionalDataHandler(displayData);
	}
	
	// get rid of current set of rows
	dwr.util.removeAllRows(tableElementId);
	
	if (displayData.length > 0) {
		var rowStyle = 1;
		var rowHandler = dataStore["rowHandler"];
		var cellStyles = dataStore["cellStyles"];
			
		// add new rows
		dwr.util.addRows(tableElementId, displayData, dataStore["cellFuncs"], {
			escapeHtml: false, 
			rowCreator:function(options) {
				var tr = document.createElement("tr");
				tr.className = "row" + rowStyle;
				rowStyle = 3 - rowStyle;
				
				var rowIndex = options["rowIndex"];
				var rowData = displayData[rowIndex];

				return rowHandler(tr, rowData);
			},
			cellCreator:function(options) {
				var td = document.createElement("td");
				
				var cellNum = options["cellNum"];
				if (cellStyles[cellNum] != "") {
					td.className += " " + cellStyles[cellNum];
				}
					
				return td;
			}
		});

		showPagingButtons(tableElementId, dataStore["page"], dataStore["maxPage"]);
	} else {
		var cf = dataStore["cellFuncs"];
		if (dataStore["dataSource"] == undefined) {
			setTableInformation(tableElementId, cf.length, "Empty");
		} else {
			setTableInformation(tableElementId, cf.length, "Nothing found");
		}
	}
}

function sortTable(tableElementId, sortColumn) {
	var dataStore = dataCache[tableElementId];
	
	var sortedData = dataStore["data"];
	
	// sanity check
	if (sortedData.length == 0) { return; }
	if (sortedData[0].length <= sortColumn) { return; }
	
	var sortedByReverse = dataStore["sortedByReverse"];
	if (dataStore["sortedBy"] == sortColumn) {
		sortedByReverse = !sortedByReverse;
	} else {
		sortedByReverse = false;
		var element = $(tableElementId + "_sortOrder_" + dataStore["sortedBy"]);
		if (element) {
			element.update("");
		}
	}
	dataStore["sortedBy"] = sortColumn;
	dataStore["sortedByReverse"] = sortedByReverse;
	
	var element = $(tableElementId + "_sortOrder_" + sortColumn);
	if (element) {
		if (sortedByReverse) {
			element.update("<img src=\"" + basePath + "images/sort_arrow_down.gif\" width=\"6\" height=\"8\" border=\"0\" />");
		} else {
			element.update("<img src=\"" + basePath + "images/sort_arrow_up.gif\" width=\"6\" height=\"8\" border=\"0\" />");
		}
	}
	
	var columnTypes = dataStore["columnTypes"];
	
	var sCol = sortColumn;
	sortedData.sort(function(row1, row2) {
		var c1 = row1[sCol];
		var c2 = row2[sCol];
		if (sortedByReverse) {
			var temp = c1;
			c1 = c2;
			c2 = temp;
		}
		var type = columnTypes[sortColumn];
		
		switch (type) {
		case "number" : return c2-c1;
		case "rnumber" : return c1-c2;
		case "percent" : return c2-c1;
		case "position" : return c1-c2;
		case "time" : return c2-c1;
		case "date" : return c2-c1;
		case "month" : return c2-c1;
		case "string" : return c1.replace(/<[^>]*>/g, "").localeCompare(c2.replace(/<[^>]*>/g, ""));
		}
		return c1.compare(c2);
	});
	
	dataStore["data"] = sortedData;
	
	dataCache[tableElementId] = dataStore;
	
	drawTable(tableElementId);
}

function showPage(tableElementId, pageNumber) {
	var dataStore = dataCache[tableElementId];

	// sanity check
	
	if (pageNumber < 1 && pageNumber != -1) {
		pageNumber = 1;
	}
	
	if (pageNumber > dataStore["maxPage"]) {
		pageNumber = dataStore["maxPage"];
	}
	
	dataStore["page"] = pageNumber;
	
	dataCache[tableElementId] = dataStore;
	
	drawTable(tableElementId);
}

function showPagingButtons(tableElementId, currentPage, maxPage) {
	if (maxPage == 1) {
		hidePagingElements(tableElementId)
		return;
	}
	
	showPagingElements(tableElementId);
	
	var html = "<ul>";
	if (currentPage != -1) {
		html += "<li class=\"viewall\"><a href=\"javascript:showPage('" + tableElementId + "',-1);\">View All</a></li>";
		if (currentPage > 1) {
			html += "<li><a href=\"javascript:showPage('" + tableElementId + "'," + (currentPage - 1) + ");\">&lsaquo; Prev</a></li>";
		}
		if (maxPage > 5) {
			var eitherSide = 2;
			
			var startNum = currentPage - eitherSide;
			var endNum = currentPage + eitherSide;
			if (startNum < 1) {
				startNum = 1;
				endNum = startNum + 4;
			}
			if (endNum > maxPage) {
				endNum = maxPage;
				startNum = endNum - 4;
			}
			
			if (startNum > 1) {
				if (currentPage != 1) {
					html += "<li><a href=\"javascript:showPage('" + tableElementId + "',1);\">1</a></li>";
				} else {
					html += "<li class=\"selected\">1</li>";
				}
			}
			if (startNum > 2) {
				html += "<li><span>...</span></li>";
			}
			
			for (var i = startNum; i <= endNum; ++i) {
				if (i != currentPage) {
					html += "<li><a href=\"javascript:showPage('" + tableElementId + "'," + i + ");\">" + i + "</a></li>";
				} else {
					html += "<li class=\"selected\">" + i + "</li>";
				}
			}
			if (endNum < maxPage - 1) {
				html += "<li><span>...</span></li>";
			}
			if (endNum < maxPage) {
				if (currentPage != maxPage) {
					html += "<li><a href=\"javascript:showPage('" + tableElementId + "'," + maxPage + ");\">" + maxPage + "</a></li>";
				} else {
					html += "<li class=\"selected\">" + maxPage + "</li>";
				}
			}
		} else {
			for (var i = 1; i <= maxPage; i++) {
				if (i == currentPage) {
					html += "<li class=\"selected\">" + i + "</li>";
				} else {
					html += "<li class=\"selected\"><a href=\"javascript:showPage('" + tableElementId + "'," + i + ");\">" + i + "</a></li>";
				}
			}
		}
		if (currentPage < maxPage) {
			html += "<li><a href=\"javascript:showPage('" + tableElementId + "'," + (currentPage + 1) + ");\">Next &rsaquo;</a></li>";
		}
	} else {
		html += "<li class=\"viewall\"><a href=\"javascript:showPage('" + tableElementId + "',1);\">View In Pages</a></li>";
	}
	html += "</ul>";

	updatePagingElements(tableElementId, html);
}

function showPagingElements(tableElementId) {
	var element = $(tableElementId + "_paging");
	
	if (element) {
		element.show();
	}
	element = $(tableElementId + "_pagingTop");
	if (element) {
		element.show();
	}
	element = $(tableElementId + "_pagingBottom");
	if (element) {
		element.show();
	}
}

function hidePagingElements(tableElementId) {
	var element = $(tableElementId + "_paging");
	if (element) {
		element.hide();
	}
	element = $(tableElementId + "_pagingTop");
	if (element) {
		element.hide();
	}
	element = $(tableElementId + "_pagingBottom");
	if (element) {
		element.hide();
	}
}

function updatePagingElements(tableElementId, html) {
	var element = $(tableElementId + "_paging");
	if (element) {
		element.update(html);
	}
	element = $(tableElementId + "_pagingTop");
	if (element) {
		element.update(html);
	}
	element = $(tableElementId + "_pagingBottom");
	if (element) {
		element.update(html);
	}
}
