/************************************************************************

History GIS MapServer

Ben Loh
Inquirium
ben@inquirium.net

Created 3/4/06


jsTimelineMgr.js
AJAX functions that load and display the dates available for each layer.

Borrows heavily from:
	Lightbox JS: Fullsize Image Overlays 
	by Lokesh Dhakar - http://www.huddletogether.com
 ************************************************************************/




/***************************************************************************
 *	TIMELINE TABLE
 *
 */

/**
 *	Returns the timeline data as an HTML Table
 *	Reads the data from 'timelineData' defined in hmapMainPage.inc via assignment to javascript from php
 *	@return	string	HTML
 *	@access	public
 */
function DisplayTimelineTable( mapID ) {
	var counter;
//	var datesArray;
	var datesList;
	var url;

	timelineHTMLTable = '<table style="background-color:#fff;">';

/*	Try no headers: They were taking up room and not adding anything.
	//	Draw Headers
	timelineHTMLTable += '<tr>';
	timelineHTMLTable += '<th>Layer</th>';			
	for (j=timelineStartDate;j<=timelineEndDate;j+=timelineIncrement) {
		timelineHTMLTable += '<th>' + j + '</th>';
	}
	timelineHTMLTable += '</tr>';			
*/
	var css = ' class="queryRow1"';
	for (var layerID in timelineData) {
		//	Catch a bug where 'toJSONstring' is being appended to the timelineData
		if (timelineData[layerID]['label'] == undefined) {
			continue;
		}
		//	Don't add it to the table if it's not in the main layer menu
		if (timelineData[layerID]['group'] != 'Main Data Layers') {
			continue;
		}		
	
		timelineHTMLTable += '<tr' + css + '>';
		timelineHTMLTable += '<td>' + timelineData[layerID]['label'] + '</td>';		
		
		if (timelineData[layerID] != undefined) {
//			datesArray = timelineData[layerID]['dates'].split(',');
			datesList = timelineData[layerID]['dates'];
			counter = 0;
			for (var date=timelineStartDate; date<=timelineEndDate; date+=timelineIncrement) {
				if ( datesList.indexOf( date ) > -1 ) {							//	If the date is found within the dateList, then we assume that it's a valid date.  This ISN'T the best way to do this...but it's cheap.
					url = '<a href="#" onClick="HandleTimelineTableDateSelect(' + date + ',\'' + layerID + '\', \'' + mapID + '\' );">';
					timelineHTMLTable += '<td>' + url + date + '</a></td>';		
				} else {
					timelineHTMLTable += '<td></td>';
				}

/*				if (counter>=datesArray.length) {
					break;
				}
				if ( parseInt( datesArray[counter] ) == date ) {
					url = '<a href="#" onClick="HandleTimelineTableDateSelect(' + date + ',\'' + layerID + '\', \'' + mapID + '\' );">';
					timelineHTMLTable += '<td>' + url + datesArray[counter] + '</a></td>';		
					counter++;
				} else {
					timelineHTMLTable += '<td>' + parseInt( datesArray[counter] ) + '</td>';
				}
*/			}
		}
		timelineHTMLTable += '</tr>';		
		if (css == ' class="queryRow1"') {
			css = ' class="queryRow2"';
		} else {
			css = ' class="queryRow1"';
		};
	}

	timelineHTMLTable += '</table>';
	
	//	Display as overlay
//	InitTimelineTable();
	var floatwin = document.getElementById('floatwin');
	ShowFloatWin( timelineHTMLTable );
	ShowOverlay();
}


/*
 *	Inserts a <div id="floatwin"></div> in the <body>
 */
function InitTimelineTable() {
/*	doesn't work.  Hacking it in for now
	var objBody		= document.getElementsByTagName("body").item(0);
	
	//	create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
	var objFloatWin	= document.createElement("div");
	objFloatWin.setAttribute('id','floatwin');
	objFloatWin.onclick 		= function () {HideFloatWin(); return false;}
	objFloatWin.style.display	= 'none';
	objFloatWin.style.position	= 'absolute';
	objFloatWin.style.top		= '100';
	objFloatWin.style.left		= '100';
	objFloatWin.style.zIndex	= '96';
 	objFloatWin.style.height 	= '400px';
 	objFloatWin.style.width 	= '400px';
	objBody.insertBefore(objFloatWin, objBody.firstChild);
	
	// create link
	var objLink = document.createElement("a");
	objLink.setAttribute('href','#');
	objLink.setAttribute('title','Close');
	objLink.innerHTML	= 'Close'; 
	objLink.onclick		= function() { HideFloatWin(); return false; }
	objFloatWin.appendChild(objLink);
	

	alert('floatwin=' + objFloatWin.innerHTML );
*/
}

function HideFloatWin() {
	var floatwin 			= document.getElementById('floatwin');
	floatwin.style.display	= 'none';		// show it!
	HideOverlay();
}

function ShowFloatWin( htmltext ) {
	var arrayPageSize	= getPageSize();	// in jsOverlay.js
	var arrayPageScroll = getPageScroll();	// in jsOverlay.js

	var floatwin = document.getElementById('floatwin');

	floatwin.innerHTML = htmltext + '<a href="#" id="closeBtn" onClick="HideFloatWin()" title="Close this window">CLOSE</a>';
	floatwin.style.display	= 'block';		// show it!
}


/**
 *	Handles selecting a date via the table
 *	Steps:
 *		2.	Select the layer (if not currently selected)
 *		1.	Set the map date
 *		3.	Submits the map
 *
 *	@access	public
 */
function HandleTimelineTableDateSelect( date, layerID, mapID ) {
//alert('HandleTimelineTableDateSelect date=' + date + ' and layerID = ' + layerID + ' and mapID = ' + mapID);
	HideFloatWin();

	var id = GetMapIDPre( mapID );
	var theMainLayerMenu			= document.getElementById( id + 'selectedMainLayer' );
	
	//	Get ready to call legendMgr.handleMainLayerMenuChange
		//	In order to call legendMgr.handleMainLayerMenuChange we need to know the mainLayerCheckBoxID.
		//	We'll just kludge it together here.
		var currentLayerID		= theMainLayerMenu.options[ theMainLayerMenu.selectedIndex ].value;
		var mainLayerCheckBoxID = GetMapIDPre( mapID ) + 'lyr' + currentLayerID;
		
		//	Because IE has disabled menu items as optgroups, we need to first re-insert the original
		//	disabled option items.
//	2007-02-21 confirm this is no longer needed
//		legendMgr.restoreDisabledOptions( mapID );
		
		//	We also need to set the selectedIndex to the new layer
		//	So we'll first walk the menu to find the right layer given our current setting
		var newSelectedIndex	= legendMgr.findMenuIndexByValue( layerID, mapID );
	
		//	Then change the selectedIndex
		theMainLayerMenu.selectedIndex	= newSelectedIndex;

	//	Then call legendMgr.handleMainLayerMenuChange (and doSubmit)
	legendMgr.changeMainLayerMenu( mainLayerCheckBoxID, mapID );

	//	Set Date only AFTER the layer is changed, otherwise we might mistakenly pick a date that isn't valid for the current layer.
	//	This wasn't a problem in non-IE browsers, but b/c IE uses a different method to disable menu items, it chokes.
	SetMapDate( date, mapID );	//	Hilites the right timeline button, sets the map date in the form, and sets the cmdStr to SetMapDate

	//	Call DoSubmit() manually.
	DoSubmit( mapID );
//alert('end of HandleTimelineTableDateSelect');
}





/***************************************************************************
 *	TIMELINE BUTTONS
 *
 */


/**
 *	Walks down the Timeline Buttons and sets the disabled state based on whether or not there is data for that 
 *	year for the currently selected main data layer.
 *	@param	string	mapID
 *	@param	string	layerName		The .map layer name, e.g. "TotalPop"
 *	@access	public
 */
function UpdateTimelineDisabledState(mapID, layerName) {
	var j;
	var counter;
	
	var datesArray = GetTimelineDataForLayerName( layerName );

//alert('UpdateTimelineDisabledState');
	if (datesArray != null) {	
		for (j=timelineStartDate;j<=timelineEndDate;j+=timelineIncrement) {
			if ( datesArray.indexOf( j ) > -1 ) {
				//	Enabled
				SetTimelineButton( mapID, j, true );
				counter++;
			} else {
				//	Disabled
				SetTimelineButton( mapID, j, false );
			}
		}	
	}
}

/**
 *	Enables/Disables the timeline button by adding/removing "disabled" to the button html
 *	@param	string	mapID
 *	@param	string	btnID			The id of the button object
 *	@param	bool	isEnabled		The new state to set the button.
 *	@access	public
 */
function SetTimelineButton( mapID, btnID, isEnabled) {
	var btnObject;
	var btnID = mapID + '_timelineBtn_' + btnID;
	
	//	Get the button object
	btnObject	= document.getElementById( btnID );
	
	if (btnObject) {
		//	Set the DOM
		if (isEnabled) {
			btnObject.disabled = false;
		} else {
			btnObject.disabled = true;
		}
		btnObject.updateDisplay();
	}
}


//	Called by the timeline to select the current date of the map
function HandleSetTimeBtn( newTime, mapID ) {
	SetMapDate( newTime, mapID );
	DoSubmit(mapID);
}

//	Called by HandleSetTimeBtn and HandleTimelineTableDateSelect to set the map date w/o submitting
function SetMapDate( newTime, mapID ) {
// 2007-02-21 don't update the timeline until after loading.  delete this if this works.
//	timelineMgr.updateTimelineButtonDisplay( newTime, mapID); 			//	Set this BEFORE calling SetCmdStr b/c SetCmdStr changes the current date and therefore leaves us unable to know which old button to change.
	//	Also set the mapDate form variable so that on submit the time will be updated
	document.forms[0][mapID+'_mapDate'].value = newTime;	//	Set this BEFORE calling SetCmdStr
	SetCmdStr('SetMapDate,'+newTime, mapID ); 	
}

/**
 *	Returns the timelineData for the layer determined by layerName
 *	@param	string	layerName		The .map layer name, e.g. "TotalPop"
 *	@return	string array			Returns the dates split into an array
 *	@access	public
 */
function GetTimelineDataForLayerName(layerName) {
	if (timelineData[layerName] != '') {
		var datesArray = timelineData[layerName]['dates'];
		return datesArray;
	} else {
		return null;
	}
}
/**
 *	Returns the human friendly label for the layer determined by layerID (aka layerName)
 *	This draws up on the JSON data read in in hmapMainPage.inc to do a translation 
 *	between the $layer->name and the metadata LYRLABEL
 *
 *	@param	string	layerID		The .map $layer->name, e.g. "TotalPop"
 *	@return	string 				Returns the human friendly label
 *	@access	public
 */
function GetLayerLabelFromTimelineData( layerID ) {
	if (timelineData[ layerID ] == undefined) {
		return '';
	} else {
		return timelineData[ layerID ]['label'];
	}
}



var TimelineMgr = {

	//  ========================================================================
	//	LOCAL VARS
	//  ========================================================================
	mapID: '',


	//  ========================================================================
	//	METHODS
	//  ========================================================================
	create:	function( newMapID ) {
		var tmgr = new Object;
		Object.extend( tmgr, TimelineMgr );
		tmgr.mapID = newMapID;
		return tmgr;
	},
	
	/*
	 *	Returns a div containing all of the timeline button elements
	 */
	getTimelineButtonsDiv: function () {
		var mapID = this.mapID.toString();	//	This is necessary b/c this.mapID is passed directly to the function

		var div = document.createElement('div');
		div.id = 'timelineBtns';
		//	Show All Button
		var btn = ABtn.create();
		btn.id = this.mapID + '_showAll';
		btn.innerHTML = 'Show&nbsp;All';
		btn.handleClick = function() {
			DisplayTimelineTable( mapID );
			return false;
		}
		btn.updateDisplay();
		div.appendChild( btn );
		//	Timeline Date Buttons
		for (var j=timelineStartDate; j<=timelineEndDate; j+=timelineIncrement) {
			var btn = ABtn.create();
			btn.id = this.mapID + '_timelineBtn_' + j;
			btn.innerHTML = j;
			btn.handleClick = function() { 
				HandleSetTimeBtn( this.innerHTML, mapID );
				return false;
			}
			btn.disabled = false;
			div.appendChild( btn );
		}

// 		var datesArray = GetTimelineDataForLayerName( legendMgr.selectedLegendLayerID );
// 		if (datesArray != null) {	
// 			for (var j=timelineStartDate; j<=timelineEndDate; j+=timelineIncrement) {
// 				var btn = ABtn.create();
// 				btn.id = this.mapID + '_timelineBtn_' + j;
// 				btn.innerHTML = j;
// 				btn.handleClick = function() { 
// 					HandleSetTimeBtn( this.innerHTML, mapID );
// 					return false;
// 				}
// 				if ( datesArray.indexOf( j ) > -1 ) {
// 					btn.disabled = false;
// 				} else {
// 					btn.disabled = true;
// 				}
// 				btn.updateDisplay();
// 				div.appendChild( btn );
// 			}	
// 		}
		return div;
	},

	/*
	 *	Updates the disabled state of all the buttons based on the currently selected layer
	 */
	updateButtonsState: function () {
		//	Timeline Date Buttons
		var datesArray = GetTimelineDataForLayerName( legendMgr.selectedLegendLayerID );
		if (datesArray != null) {	
			for (var j=timelineStartDate; j<=timelineEndDate; j+=timelineIncrement) {
				var btn = document.getElementById( this.mapID + '_timelineBtn_' + j );
				if ( datesArray.indexOf( j ) > -1 ) {
					btn.disabled = false;
				} else {
					btn.disabled = true;
				}
				btn.updateDisplay();
			}	
		}
	},

	//	Update the timeline buttons to display the new time
	updateTimelineButtonDisplay: function() {
		var currentTime = document.forms[0][this.mapID+'_mapDate'].value;			//	This HAS to be done before SetCmdStr (or we'll lose the current date)
		//	Turn on the new button
		tl = document.getElementById( this.mapID + '_timelineBtn_' + currentTime );
		if (tl) {
			tl.state = 'on';
			tl.updateDisplay();
		}
	}

}

