
  /////////////////////////////////////////////////////
  //                                                 //
  //          C-NOOFS Forecast Viewer v0.6           //
  //               Web User Interface                //
  //                                                 //
  /////////////////////////////////////////////////////

/**
 * Results Table class
 * @param id Identifier for this table
 */
ResultsTable = function(id, TBLCFG)
{
	this.id = id;
	this.container = new Object();
	this.TableHeader = new Object();
	this.TableBody = new Object();
	this.TableFooter = new Object();
	this.TableConfig = new Object();
	
	// Container to hold the table
	this.container = document.createElement("div");
	this.container.className = "tableContainer";
		
		// Add the top pagination bar
		var pag = document.createElement("div");
		pag.className="RT_" + id + "_PAG";
		
	this.container.appendChild(pag);

		// Create the table element
		var tbl = document.createElement("table");
		tbl.id="RT_" + id;
		tbl.className="resultsTable";
		
			// Create the table header
			var tHead = document.createElement("thead");

				// Create the first header row			
				var tHeadRowOne = document.createElement("tr");	
				
					// Create the "Forecasted Date" column
					var tHeadFcstDate = document.createElement("td");
					tHeadFcstDate.rowSpan = 2;
					tHeadFcstDate.sortable = true;
					tHeadFcstDate.style.width = "28%";
					tHeadFcstDate.innerHTML = TBLCFG.Translation.Headers.ForecastedDate;
				
				tHeadRowOne.appendChild(tHeadFcstDate);
				
					// Create the "Forecast Offset" column
					var tHeadFcstOffset = document.createElement("td");
					tHeadFcstOffset.rowSpan = 2;
					tHeadFcstOffset.sortable = true;
					tHeadFcstOffset.style.width = "32%";
					tHeadFcstOffset.innerHTML = TBLCFG.Translation.Headers.RunDate;
				
				tHeadRowOne.appendChild(tHeadFcstOffset);
				
					// Create the "Water Depth" column
					var tHeadWaterDepth = document.createElement("td");
					tHeadWaterDepth.rowSpan = 2;
					tHeadWaterDepth.sortable = true;
					tHeadWaterDepth.innerHTML = TBLCFG.Translation.Headers.WaterDepth;
				
				tHeadRowOne.appendChild(tHeadWaterDepth);
				
					// Create the "Datasets" column
					var tHeadFcstDate = document.createElement("td");
					tHeadFcstDate.className = "last centered smallerText";
					tHeadFcstDate.colSpan = 3;
					tHeadFcstDate.style.width = "25%";
					tHeadFcstDate.sortable = false;
					tHeadFcstDate.innerHTML = TBLCFG.Translation.Headers.DataSets;
				
				tHeadRowOne.appendChild(tHeadFcstDate);
				
			tHead.appendChild(tHeadRowOne);

				// Create the second header row	
				var tHeadRowTwo = document.createElement("tr");	
				tHeadRowTwo.className="subRow smallerText";
				
					// Create the "Datasets" column
					var tHeadDSName = document.createElement("td");
					tHeadDSName.className = "subRow";
					tHeadDSName.innerHTML = TBLCFG.Translation.Headers.Variable;
				
				tHeadRowTwo.appendChild(tHeadDSName);

					// Create the "1/4 degree" column
					var tHeadRes4 = document.createElement("td");
					tHeadRes4.className = "subRow centered";
					tHeadRes4.innerHTML = "<abbr title=\"" + CFG.DataSets.Resolutions[0] + "\">" + TBLCFG.Translation.Headers.Resolution4 + "</abbr>";
				
				tHeadRowTwo.appendChild(tHeadRes4);

					// Create the "1/12 degree" column
					var tHeadRes12 = document.createElement("td");
					tHeadRes12.className = "subRow centered";
					tHeadRes12.innerHTML = "<abbr title=\"" + CFG.DataSets.Resolutions[1] + "\">" + TBLCFG.Translation.Headers.Resolution12 + "</abbr>";
				
				tHeadRowTwo.appendChild(tHeadRes12);

			tHead.appendChild(tHeadRowTwo);
				
		tbl.appendChild(tHead);			
		
			// Create the table footer
			var tFoot = document.createElement("tfoot");
		
		tbl.appendChild(tFoot);		
		
			// Create the table body
			var tBody = document.createElement("tbody");

		tbl.appendChild(tBody);
						
	this.container.appendChild(tbl);
		
		// Add the bottom pagination bar
		var pag = document.createElement("div");
		pag.className="RT_" + id + "_PAG";
		
	this.container.appendChild(pag);

	// Save some references
	this.TableHeader = tHead;
	this.TableBody = tBody;
	this.TableFooter = tFoot;
	this.TableConfig = TBLCFG;
	
	this.TBR = new ResultsTable.TableBodyWrapper(this.TableBody);
}

/**
 * Identifier of this table
 * @type string
 */
ResultsTable.prototype.id = ""
ResultsTable.prototype.getID = function() { return this.id; }


ResultsTable.prototype.TableHeader;
ResultsTable.prototype.TableBody;
ResultsTable.prototype.TableFooter;
ResultsTable.prototype.TableConfig;
ResultsTable.prototype.getTableConfig = function() { return this.TableConfig; }


/**
 * Defines the container for the table
 * @type HTMLDivElement
 */
ResultsTable.prototype.container;
ResultsTable.prototype.getContainer = function() { return this.container; }


ResultsTable.prototype.updatePagination = function(TBLUP,SelectedPage, AvailablePages)
{
	if ( AvailablePages < 2 ) return;
	
	// Update the pagination
	var pagBars = YAHOO.util.Dom.getElementsByClassName("RT_" + this.getID() + "_PAG", null, this.getContainer());
	if ( pagBars.length > 0 )
	{
		for ( var i = 0; i < pagBars.length; i++ )
		{
			var pagBar = pagBars[i];				
			pagBar.className = "RT_" + this.getID() + "_PAG pagination";
			for(var k=pagBar.childNodes.length-1;k>=0;k--) pagBar.removeChild(pagBar.childNodes[k]);
			var pageLinks = document.createElement("div");
			pageLinks.className = "pageLinks";

			var NOP = this.TableConfig.Pagination.NumberOfPages;
			if ( NOP >= AvailablePages )
			{
				var pgStart = 1;
				var pgEnd = AvailablePages;
			}
			else
			{
				var pgStart = SelectedPage - Math.ceil( NOP / 2 );
				if ( pgStart <= 0 ) pgStart = 1;
				var pgEnd = Math.abs(pgStart) + NOP;
				if ( pgEnd > AvailablePages )
				{
				 	pgStart = pgStart - (pgEnd - AvailablePages);
					if ( pgStart <= 0 ) pgStart = 1;
					pgEnd = AvailablePages;
				}
			}

			if ( SelectedPage != 1 )
			{
				var pgNum = document.createElement("a");
				var pgNumEl = new YAHOO.util.Element(pgNum);
				pgNum.className = "pageLink";
				pgNum.innerHTML = "&laquo;";
				pgNum.pgNum = 1;
				pgNum.href = "#";
				pgNumEl.on("click",function(e)
				{
					if ( this.get('element').pgNum > 0 && this.get('element').pgNum <= AvailablePages )
					{
						TBLUP.currentPage = this.get('element').pgNum;
						ViewerInterface.RenderProcessingBox();
						TBLUP.triggerUpdate();
					}
				});
				pageLinks.appendChild(pgNum);
			}

			for ( var j = pgStart; j <= pgEnd; j++ )
			{
				var pgNum = document.createElement("a");
				var pgNumEl = new YAHOO.util.Element(pgNum);
				pgNum.className = "pageLink";
				if ( j == SelectedPage ) pgNum.className += " selected";
				pgNum.innerHTML = j;
				pgNum.pgNum = j;
				pgNum.href = "#";
				
				pgNumEl.on("click",function(e)
				{
					if ( this.get('element').pgNum > 0 && this.get('element').pgNum <= AvailablePages )
					{
						TBLUP.currentPage = this.get('element').pgNum;
						ViewerInterface.RenderProcessingBox();
						TBLUP.triggerUpdate();
					}
				});
				
				pageLinks.appendChild(pgNum);
			}
			
			if ( SelectedPage != AvailablePages )
			{
				var pgNum = document.createElement("a");
				var pgNumEl = new YAHOO.util.Element(pgNum);
				pgNum.className = "pageLink";
				pgNum.innerHTML = "&raquo;";
				pgNum.pgNum = AvailablePages;
				pgNum.href = "#";
				pgNumEl.on("click",function(e)
				{
					if ( this.get('element').pgNum > 0 && this.get('element').pgNum <= AvailablePages )
					{
						TBLUP.currentPage = this.get('element').pgNum;
						ViewerInterface.RenderProcessingBox();
						TBLUP.triggerUpdate();
					}
				});
				pageLinks.appendChild(pgNum);
			}

			pagBar.appendChild(pageLinks);
		}
	}
}

ResultsTable.prototype.clearPagination = function()
{
	var pagBars = YAHOO.util.Dom.getElementsByClassName("RT_" + this.getID() + "_PAG", null, this.getContainer());
	if ( pagBars.length > 0 )
	{
		for ( var i = 0; i < pagBars.length; i++ )
		{
			nodeCount = pagBars[i].childNodes.length;
			for(var j=nodeCount-1;j>=0;j--)
			{
				pagBars[i].removeChild(pagBars[i].childNodes[j]);
			}
		}
	}
}




ResultsTable.popupImage = function(img_id)
{
	var tblCell = document.getElementById(img_id);
	if ( tblCell != null && !YAHOO.lang.isUndefined(tblCell) )
	{
		if ( tblCell.RowData.ItemID > 0 )
		{
			var nWin = window.open('',img_id,'status=no,resizable=yes,width=740,height=657');
			var body = nWin.document.body;
			
			if ( body != null && !YAHOO.lang.isUndefined(nWin.document.body) )
			{
				var image = nWin.document.createElement("img");
				image.style.width = "100%";
				image.style.height = "100%";
				image.src = tblCell.RowData.FullImage;
				body.appendChild(image);
			}			
		}
	}
}

///////////////////////////////////////////////////////////////////////////////

ResultsTable.TableBodyWrapper = function(tblbody)
{
	this.TableBody = tblbody;
};

ResultsTable.TableBodyWrapper.prototype.TableBody = new Object();
ResultsTable.TableBodyWrapper.prototype.TableRows = new Array();

ResultsTable.TableBodyWrapper.prototype.removeAllRows = function()
{
	this.TableRows = new Array();
	var nodeCount = this.TableBody.childNodes.length;
	for(var i=nodeCount-1;i>=0;i--)
	{
		this.TableBody.removeChild(this.TableBody.childNodes[i]);
	}

}

ResultsTable.TableBodyWrapper.prototype.removeRow = function(rowID)
{
	alert(document.getElementById(rowID));
}

ResultsTable.TableBodyWrapper.prototype.rowClass = "";
ResultsTable.TableBodyWrapper.prototype.addRow = function(rData,TBLUP)
{
	var NumVariables = ( rData.Depth == 0 ) ? CFG.DataSets.NumVars3D + CFG.DataSets.NumVars2D : CFG.DataSets.NumVars3D;

		// Generate a new row 
		var newRow = document.createElement("tr");
		newRow.className = this.rowClass;
		newRow.id = rData.id;
		
			// Create the "Forecasted Date" column
			var fcstDate = document.createElement("td");
			fcstDate.rowSpan = NumVariables + 1;
			fcstDate.innerHTML = this._dateFormat(new Date(parseInt(rData.FcstDate) * 1000));

		newRow.appendChild(fcstDate);
		
			// Create the "Run Date" Column
			var runDate = document.createElement("td");
			runDate.rowSpan = NumVariables + 1;
			offset = Math.floor((rData.FcstDate - rData.RunDate) / 86400);
			runDate.innerHTML = this._dateFormat(new Date(parseInt(rData.RunDate) * 1000)) + " (+" + offset + ")";
			
		newRow.appendChild(runDate);
		
			// Create the "Depth" column
			var runDepth = document.createElement("td");
			runDepth.rowSpan = NumVariables + 1;
			runDepth.innerHTML = rData.Depth + "m";
			
		newRow.appendChild(runDepth);
	
		this.TableBody.appendChild(newRow);

		for ( var key = 0; key < NumVariables; key++ )
		{
			var tmpRow = document.createElement("tr");
			tmpRow.className = newRow.className + " smallerText";
			
				var colVariable = document.createElement("td");
				colVariable.innerHTML = Lang.DataSets[CFG.DataSets.Variables[key]];
				
				tmpRow.appendChild(colVariable);

				var reskey = "";
				for ( reskey in CFG.DataSets.Resolutions )
				{
					var colRes = document.createElement("td");
					colRes.id = rData.RunDate + "_" + rData.FcstDate + "_" + rData.Depth + "_" + CFG.DataSets.Variables[key] + "_" + CFG.DataSets.Resolutions[reskey];
					colRes.className = "centered";
				 	if ( rData.RunState == 'P' )
				 	{
			 	 		colRes.innerHTML = "<img src=\"images/ajax-loader.gif\" alt=\"P\" />";
				 	}
					else
					{
			 	 		colRes.innerHTML = "-";
					}
					tmpRow.appendChild(colRes);
				}
			
			this.TableBody.appendChild(tmpRow);
		}
		
	this.TableRows.push(rData);
	
	this.updateRow(rData);
}


ResultsTable.TableBodyWrapper.prototype.showEmptyBodyMessage = function()
{
	this.removeAllRows();
	
	// Generate a new row 
	var newRow = document.createElement("tr");
	newRow.className = "even";
	
		var theTD = document.createElement("td");
		theTD.className = "centered";
		theTD.style.padding = "12px";
		theTD.colSpan = 6;		
		theTD.innerHTML = Lang.ResultsTable.NoRecordsFound;
		
	newRow.appendChild(theTD);
	this.TableBody.appendChild(newRow);	
}


ResultsTable.TableBodyWrapper.prototype.updateRow = function(rData)
{
	for ( var resolution in rData.Models )
	{
		for ( var key in rData.Models[resolution].Images )
		{
		 	var image = rData.Models[resolution].Images[key];
			var cell = document.getElementById(rData.RunDate + "_" + rData.FcstDate + "_" + rData.Depth+ "_" + image.DataSet + "_" + resolution);
			if ( cell != null && !YAHOO.lang.isUndefined(cell) )
			{
			 	cell.RowData = image;
	 	 		cell.innerHTML = "<a href=\"#\" onclick=\"javascript:ResultsTable.popupImage('" + cell.id + "');\"><img src=\"images/view_image.png\" alt=\"V\" title=\"" + Lang.ResultsTable.ClickHereToViewImage + "\" /></a>";
			}
		}
	}
}




ResultsTable.TableBodyWrapper.prototype._dateFormat = function(dateObj)
{
	var dateStr = CFG.DateFormat.Normal;
	
	dateStr = dateStr.replace("%AbbrMonth", Lang.Date.AbbrMonth[dateObj.getMonth()+1]);
	dateStr = dateStr.replace("%Month", dateObj.getMonth());
	dateStr = dateStr.replace("%Day", dateObj.getDate());
	dateStr = dateStr.replace("%Year", dateObj.getFullYear());
	dateStr = dateStr.replace("%Hour", ( dateObj.getHours() < 10 ) ? "0" + dateObj.getHours() : dateObj.getHours());
	dateStr = dateStr.replace("%Minute", ( dateObj.getMinutes() < 10 ) ? "0" + dateObj.getMinutes() : dateObj.getMinutes());
	dateStr = dateStr.replace("%Second", ( dateObj.getSeconds() < 10 ) ? "0" + dateObj.getSeconds() : dateObj.getSeconds());
	
	var tmpDay = dateObj.getDate().toString();
	var tmpDayTens = tmpDay.slice(0);
	tmpDay = tmpDay.slice(tmpDay.length-1);

	dateStr = dateStr.replace("%DaySuffix",  ( ( tmpDayTens >= 10 && tmpDayTens <= 20 ) ? Lang.Date.DaySuffix[0] : Lang.Date.DaySuffix[tmpDay] ) );	

	return dateStr;
}


///////////////////////////////////////////////////////////////////////////////

ResultsTable.prototype.TBR = new Object();
ResultsTable.prototype.getTableBody = function() { return this.TBR; }

