// -----------------------------------------------
// Sortable Table
// -----------------------------------------------

SortableTable = function (tableId, linesPerPage) {
	this._tableId = tableId;
	if (linesPerPage > 0) {
		this._linesPerPage = linesPerPage;
	}
}

SortableTable.prototype = {
	_tableData: [],
	_tableId: null,
	_linesPerPage: 5,
	_startIndex: 0,
	_totalPages: 0,

	_loadingId_on: null,
	_loadingId_off: null,

	_columnFunctions: new Array(),
	_foundResultsFunction: null,
	_noResultsFunction: null,
	_errorResultsFunction: null,

	setLoadingId: function(id_on, id_off) {
		this._loadingId_on = id_on;
		this._loadingId_off = id_off;
	},

	setColumnFunction: function(index, func) {
		if (index == null || index < 0) return;

		if (this._columnFunctions.length == 0) {
			this._columnFunctions = new Array();
		}

		var funcObj = new Array();
		if (arguments.length > 0) {
			funcObj.pointer = func;
		} else {
			funcObj.pointer = null;
		}

		funcObj.params = new Array();
		for (var i=2; i<arguments.length; i++) {
			funcObj.params.push(arguments[i]);
		}

		this._columnFunctions[index] = funcObj;
	},

	setFoundResultsFunction: function(func) {
		this._foundResultsFunction = func;
	},

	setNoResultsFunction: function(func) {
		this._noResultsFunction = func;
	},

	setErrorResultsFunction: function(func) {
		this._errorResultsFunction = func;
	},

	setTable: function(url) {
		this._startIndex = 0;
		var req = SortableTable.HttpRequest.create();
		if (req == null) return null;

		// Add time parameter to get the latest data from server
		if (url.indexOf("?") > -1) {
			url = url + "&t=" + (new Date()).getTime();
		} else {
			url = url + "?t=" + (new Date()).getTime();
		}

		var thisTable = this;
		req.onreadystatechange = function () {
			if (req.readyState == 4) {
				if(req.status == 200){
					SortableTable.HttpRequest.callback(thisTable, req);
				} else {
					SortableTable.Utils.setHTML(thisTable._tableId, (thisTable._errorResultsFunction == null ? "Sorry, an error occurred." : thisTable._errorResultsFunction()));
				}
			}
		}

		// Init data and show loading message
		this._startIndex = 0;
		this._totalPages = 1;
		this._showPageNavPosition();
		this._showGoToPageContainer();
		this._showLoading();

		req.open("GET", url , true);
		req.send(null);
	},

	sortTable: function(sortIndex, sortOrder) {
		if (sortOrder == null || sortOrder.toLowerCase().indexOf("desc") > -1) {
			sortOrder = -1; // desc
		} else {
			sortOrder = 1; // asc
		}

		this._tableData.sort(function(a,b) { return (SortableTable.Utils.sort(a[sortIndex], b[sortIndex])) * sortOrder; });
		this._createTable();
	},

	hasPage: function(pageNumber) {
		if (isNaN(pageNumber)) return false;
		if (pageNumber >= 1 && pageNumber <= this._totalPages) {
			return true;
		}
		return false;
	},

	hasPreviousPage: function() {
		if (this._startIndex - this._linesPerPage >= 0) {
			return true;
		}
		return false;
	},

	hasNextPage: function() {
		if (this._startIndex + this._linesPerPage < this.getTotalRows()) {
			return true;
		}
		return false;
	},

	goPage: function(pageNumber, errorId) {
		if (errorId == null) {
			if (isNaN(pageNumber) || pageNumber < 1) {
				pageNumber = 1;
			} else if (pageNumber > this._totalPages) {
				pageNumber = this._totalPages;
			}
		} else {
			if (isNaN(pageNumber) || pageNumber < 1 || pageNumber > this._totalPages) {
				var element = document.getElementById(errorId);
				if (element != null) {
					element.style.display = "inline";
				}
				return;
			} else {
				var element = document.getElementById(errorId);
				if (element != null) {
					element.style.display = "none";
				}
			}
		}

		pageNumber = parseInt(pageNumber);
		if (pageNumber == this.getCurrentPageNumber()) {
			return;
		}

		this._startIndex = (pageNumber - 1) * this._linesPerPage;
		this._createTable();
	},

	previousPage: function() {
		if (!this.hasPreviousPage()) return;
		this._startIndex -= this._linesPerPage;
		this._createTable();
	},

	nextPage: function() {
		if (!this.hasNextPage()) return;
		this._startIndex += this._linesPerPage;
		this._createTable();
	},

	getCurrentPageNumber: function() {
		return parseInt(this._startIndex / this._linesPerPage) + 1;
	},

	getTotalPages: function() {
		return this._totalPages;
	},

	getTotalRows: function() {
		return this._tableData.length;
	},

	_createTable: function() {
		if (this._tableId == null) return;

		var tableElement = document.getElementById(this._tableId);
		if (tableElement == null) return;

		this._showCurrentPageNumber();

		var row = this.getTotalRows();
		if (row == 0) {
			tableElement.innerHTML = (this._noResultsFunction == null ? "" : this._noResultsFunction());
			return;
		} else if (this._foundResultsFunction != null) {
			this._foundResultsFunction();
		}

		var col = this._tableData[0].length;

		var startRow = this._startIndex;
		if (startRow < 0) startRow = 0;

		var endRow = startRow + this._linesPerPage;
		if (endRow > row) endRow = row;

		var buf = [];
		buf.push("<table>");
		for (var i=startRow; i<endRow; i++) {
			if (((i-startRow) % 2) == 0) {
				buf.push("<tr class=\"grey_row\">");
			} else {
				buf.push("<tr>");
			}

			for (var j=0; j<col; j++) {
				var value = this._tableData[i][j];
				if (this._columnFunctions[j] != null) {
					var func = this._columnFunctions[j];
					if (func.pointer != null) {
						buf.push(func.pointer(value, func.params));
					} else {
						buf.push("<td>"+(value==null?"":value)+"</td>");
					}
				} else {
					buf.push("<td>"+(value==null?"":value)+"</td>");
				}
			}
			buf.push("</tr>");
		}
		buf.push("</table>");

		tableElement.innerHTML = buf.join("");
	},

	_showLoading: function() {
		if (this._loadingId_off != null) {
			var elements = document.getElementsByName(this._loadingId_off);
			for (var i=0; i<elements.length; i++) {
				elements[i].style.display = "none";
			}
		}

		if (this._loadingId_on != null) {
			var elements = document.getElementsByName(this._loadingId_on);
			for (var i=0; i<elements.length; i++) {
				elements[i].style.display = "block";
			}
		}
	},

	_hideLoading: function() {
		if (this._loadingId_on != null) {
			var elements = document.getElementsByName(this._loadingId_on);
			for (var i=0; i<elements.length; i++) {
				elements[i].style.display = "none";
			}
		}

		if (this._loadingId_off != null) {
			var elements = document.getElementsByName(this._loadingId_off);
			for (var i=0; i<elements.length; i++) {
				elements[i].style.display = "block";
			}
		}
	},

	_showTotalRows: function() {
		if (this._tableId != null) {
			var elements = document.getElementsByName(this._tableId+"_totalRows");
			for (var i=0; i<elements.length; i++) {
				elements[i].innerHTML = this.getTotalRows();
			}
		}
	},

	_showCurrentPageNumber: function() {
		if (this._tableId != null) {
			var elements = document.getElementsByName(this._tableId+"_currentPageNumber");
			for (var i=0; i<elements.length; i++) {
				elements[i].innerHTML = this.getCurrentPageNumber();
			}
			this._showPageNavPosition();
		}
	},

	_showTotalPages: function() {
		if (this._tableId != null) {
			var elements = document.getElementsByName(this._tableId+"_totalPages");
			for (var i=0; i<elements.length; i++) {
				elements[i].innerHTML = this.getTotalPages();
			}
		}
	},

	_showPageNavPosition: function() {
		var elements = document.getElementsByName("pageNavPosition_prevBtn");
		for (var i=0; i<elements.length; i++) {
			if (this.getCurrentPageNumber() <= 1) {
				elements[i].style.display = 'none';
			} else {
				elements[i].style.display = 'inline';
			}
		}

		elements = document.getElementsByName("pageNavPosition_prevSpc");
		for (var i=0; i<elements.length; i++) {
			if (this.getCurrentPageNumber() <= 1) {
				elements[i].style.display = 'inline';
			} else {
				elements[i].style.display = 'none';
			}
		}

		elements = document.getElementsByName("pageNavPosition_nextBtn");
		for (var i=0; i<elements.length; i++) {
			if (this.getCurrentPageNumber() >= this.getTotalPages()) {
				elements[i].style.display = 'none';
			} else {
				elements[i].style.display = 'inline';
			}
		}

		elements = document.getElementsByName("pageNavPosition_nextSpc");
		for (var i=0; i<elements.length; i++) {
			if (this.getCurrentPageNumber() >= this.getTotalPages()) {
				elements[i].style.display = 'inline';
			} else {
				elements[i].style.display = 'none';
			}
		}

		elements = document.getElementsByName("pageNavPosition");
		for (var i=0; i<elements.length; i++) {
			if (this.getTotalPages() <= 1) {
				elements[i].style.display = 'none';
			} else {
				elements[i].style.display = 'block';
			}
		}
	},

	_showGoToPageContainer: function() {
		var elements = document.getElementsByName("go_to_page_container");
		for (var i=0; i<elements.length; i++) {
			if (this.getTotalPages() == 1) {
				elements[i].style.display = 'none';
			} else {
				elements[i].style.display = 'block';
			}
		}
	}

}

SortableTable.Utils = {

	setHTML: function(id, html) {
		if (id != null) {
			if (html == null) html = "";

			var element = document.getElementById(id);
			if (element != null) {
				element.innerHTML = html;
			}
		}
	},

	trim: function(s) {
		if (s == null) { return s; }
		return s.replace(/^\s+|\s+$/g, "");
	},

	sort: function(a, b) {
		var va = SortableTable.Utils._getSortKey(a);
		var vb = SortableTable.Utils._getSortKey(b);

		if (isNaN(va) || isNaN(vb)) {
			return SortableTable.Utils._strcomp(va, vb);
		}
		return va - vb;
	},

	_getSortKey: function(obj) {
		var sortKey = obj;

		try {
			if (sortKey instanceof Object && sortKey.name != null) {
				sortKey = sortKey.name;
			}
		} catch (e) {}

		return sortKey;
	},

	_strcomp: function(a, b) {
		for (var i=0; i<a.length && i<b.length; i++) {
			var ca = a.charCodeAt(i);
			var cb = b.charCodeAt(i);
			if (ca != cb) {
				return ca - cb;
			}
		}
		return a.length - b.length;
	}

}

SortableTable.HttpRequest = {

	create: function() {
		if(window.ActiveXObject) {
			try { return new ActiveXObject("Msxml2.XMLHTTP"); }
			catch (e) {
				try { return new ActiveXObject("Microsoft.XMLHTTP"); }
				catch (e2) {}
			}
		} else if (window.XMLHttpRequest) {
			try { return new XMLHttpRequest(); }
			catch (e) {}
		}
		return false;
	},

	callback: function(tbl, req) {
		tbl._hideLoading();

		tbl._tableData = JSON.parse(req.responseText);
		tbl._startIndex = 0;
		tbl._totalPages = parseInt((tbl.getTotalRows()-1) / tbl._linesPerPage) + 1;

		tbl._showTotalRows();
		tbl._showTotalPages();
		tbl._showPageNavPosition();
		tbl._showGoToPageContainer();

		tbl._createTable();
	}

}

