var SNMOBILE = (function() {
	var gImageNeedsRefresh = false;
	var kDefaultMobileAlt = 20; // this seems to work better than the default alt stored in 
	
	// -------------------------------------------------
	//	readPrefs
	// -------------------------------------------------
	function readPrefs(inSituation)
	{
		if (!inSituation) {
			return;
		}
	
		if (document.cookie) {
			var cookiesA = document.cookie.split(';');
			var prefs = {};
			var values = [];
			for(var i = 0; i < cookiesA.length; i +=1) {
				values = cookiesA[i].split("=");
				prefs[values[0].replace(/^\s+/g, '')] = values[1]; // need to remove any leading whitespace
			}
			
			// read in the location
			for (var x in inSituation.location)
			{
				if (typeof(inSituation.location[x]) != "function") {
					if (prefs[x]) {
						inSituation.location[x] = prefs[x];	
					}
				}
			}
		}
	}
	
	// -------------------------------------------------
	//	writePrefs
	// -------------------------------------------------
	function writePrefs(inSituation)
	{
		if (!inSituation) {
			return;
		}
	
		// just write out the location
		for (var x in inSituation.location)
		{
			if (typeof(inSituation.location[x]) != "function")
			{
				document.cookie = x + "=" + inSituation.location[x]; // write out all members that are not functions
			}
		}
	}
	
		
	// -------------------------------------------------
	//	isSNInPortrait
	// -------------------------------------------------
	function isSNInPortrait()
	{
		var cssElem = $('cssFile');
		var urlComps = cssElem.href.split('/');
		var fileName = urlComps[urlComps.length-1];
		if (fileName == "sniphone-p.css") {
			return true;
		}
		else {
			return false;
		}
	}
	
	// -------------------------------------------------
	//	setToPortrait
	// -------------------------------------------------
	function setToPortrait()
	{
		var cssElem = $('cssFile');
		cssElem.href = "style/sniphone-p.css"; // it's ok to pass back a relative URL
		SNWEBVIEW.refreshImage();
	}
	
	// -------------------------------------------------
	//	setToLandscape
	// -------------------------------------------------
	function setToLandscape()
	{
		var cssElem = $('cssFile');
		cssElem.href = "style/sniphone-l.css"; // it's ok to pass back a relative URL
		SNWEBVIEW.refreshImage();
	}
	
	
	// -------------------------------------------------
	//	populateDaysPopup
	// -------------------------------------------------
	function populateDaysPopup(inSituation)
	{	
		var numDays = SNWEB.utils.getDaysInMonth(inSituation.dateTime.getFullYear(), inSituation.dateTime.getMonth());
		var daysElement = $("dayPopup");
	
		var optionNode = null;
	
		// remove all of the elements;
		while (daysElement.lastChild !== null)
		{
			daysElement.removeChild(daysElement.lastChild);
		}
		
		for (var i = 1; i <= numDays; i+= 1)
		{
			optionNode = document.createElement("option");
			optionNode.value = i.toString();
			optionNode.innerHTML = i.toString();
			daysElement.appendChild(optionNode);
		}
	}
	
	// -------------------------------------------------
	//	populateYearsPopup
	// -------------------------------------------------
	function populateYearsPopup(inSituation)
	{	
		var yearsElement = $("yearPopup");
	
		var optionNode = null;
	
		// remove all of the elements;
		while (yearsElement.lastChild !== null)
		{
			yearsElement.removeChild(yearsElement.lastChild);
		}
		
		var currentYear = inSituation.dateTime.getFullYear();
		for (var i = (currentYear - 10); i <= (currentYear + 10); i+= 1)
		{
			optionNode = document.createElement("option");
			optionNode.value = i.toString();
			optionNode.innerHTML = i.toString();
			yearsElement.appendChild(optionNode);
		}
	}
	
	// -------------------------------------------------
	//	homeView
	// -------------------------------------------------
	function homeView(inEvt)
	{
		// event handling boilerplate
		inEvt = inEvt || event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
	
		SNWEBVIEW.situation.gaze.FOV = SNWEB.consts.kDefaultFOV;
		SNWEBVIEW.situation.gaze.alt = kDefaultMobileAlt;
		SNWEBVIEW.situation.gaze.az = SNWEB.consts.kDefaultAzimuth;
	
		SNWEBVIEW.refreshImage();
	}
	
	
	// -------------------------------------------------
	//	monthChanged
	// -------------------------------------------------
	function monthChanged(inEvt)
	{
		// event handling boilerplate
		inEvt = inEvt || event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
		
		populateDaysPopup(SNWEBVIEW.situation);
		$("dayPopup").value	= SNWEBVIEW.situation.dateTime.getDate();
		setMonthPadding();
	}
	
	// -------------------------------------------------
	//	setControlsToMatchSituation
	// -------------------------------------------------
	function setControlsToMatchSituation(inSituation)
	{
		if (!inSituation) {
			return;
		}
	
		setSwitch($("showDaylightChk"),			!!(inSituation.options.daylight));
		setSwitch($("showHorizonChk"),			!!(inSituation.options.horizon));
		setSwitch($("showConstellationsChk"),	!!(inSituation.options.constellations));
		setSwitch($("showPlanetLabelsChk"),		!!(inSituation.options.planetLabels));
		setSwitch($("showStarLabelsChk"),		!!(inSituation.options.starLabels));
					
		var lat = Number(inSituation.location.lat);
		var lng = Number(inSituation.location.lng);
	
		if (SNWEBVIEW.flowingTime === true) {
			setSwitch($("useCurrDT"),true);
			disableDateAndTime();
		} else {
			setSwitch($("useCurrDT"),false);
			enableDateAndTime();
		}
		
		// even if above, it's ok to set these to the correct values
		var hour = Number(inSituation.dateTime.getHours());
		if (hour === 0) {
			hour = 12;
			$("ampmPopup").value = "AM";
		}
		else if (hour === 12) {
			$("ampmPopup").value = "PM";
		}
		else if (hour > 12) {
			hour -= 12;
			$("ampmPopup").value = "PM";
		}
		else {
			$("ampmPopup").value = "AM";
		}
		$("hoursPopup").value		= hour;
	
		$("minutesPopup").value		= (Math.floor(inSituation.dateTime.getMinutes() / 5)) * 5; // round to nearest 5 minute 
		
		$("dayPopup").value			= inSituation.dateTime.getDate();
		$("monthPopup").value		= inSituation.dateTime.getMonth();
		$("yearPopup").value		= inSituation.dateTime.getFullYear();
	
		setHoursPadding();
		setDayWidth();
		setMonthPadding();
	
		setSwitch($("useDSTChk"), !!(inSituation.location.useDST));
	}
	
	// -------------------------------------------------
	//	setSituationToMatchControls
	// -------------------------------------------------
	function setSituationToMatchControls(inSituation)
	{
		if (!inSituation) {
			return;
		}
		
		// Date
		// A quick check for the days (note that we MUST set date first since it may be over the max for that month )
		var numDaysInMonth = SNWEB.utils.getDaysInMonth(parseInt($("yearPopup").value, 10), parseInt($("monthPopup").value, 10));
		if (parseInt($("dayPopup").value, 10) > numDaysInMonth)
		{
			inSituation.dateTime.setDate(numDaysInMonth);
		}
		else
		{
			inSituation.dateTime.setDate(parseInt($("dayPopup").value, 10));
		}
	
		inSituation.dateTime.setMonth(parseInt($("monthPopup").value, 10));
		inSituation.dateTime.setFullYear(parseInt($("yearPopup").value, 10));
		
	
		// Time
		if (getSwitch($("useCurrDT")))
		{
			SNWEBVIEW.flowingTime = true;
			
			// If we're passing a timezone, we need to also use UTC not the computer's local clock time
			inSituation.useTimezoneAndUTC = true; 
			inSituation.dateTime.setTime(new Date()); // sets the time to now
		}
		else
		{
			SNWEBVIEW.flowingTime = false;
	
			// if we're simply passing a local time, we don't need timezone info.
			inSituation.useTimezoneAndUTC = false;
			
			var hour = parseInt($("hoursPopup").value, 10);
			if ($("ampmPopup").value == "PM") {
				if (hour != 12) {
					hour += 12;
				}			
			} else {
				if (hour == 12) {
					hour = 0;
				}
			}
			
			
			inSituation.dateTime.setHours(hour);
			inSituation.dateTime.setMinutes(parseInt($("minutesPopup").value, 10));
			inSituation.dateTime.setSeconds("00");
		}
		
		// Location
		inSituation.location.useDST			= getSwitch($("useDSTChk"));
		
		// Options
		inSituation.options.daylight		= getSwitch($("showDaylightChk"));
		inSituation.options.horizon			= getSwitch($("showHorizonChk"));
		inSituation.options.constellations	= getSwitch($("showConstellationsChk"));
		inSituation.options.planetLabels	= getSwitch($("showPlanetLabelsChk"));
		inSituation.options.starLabels		= getSwitch($("showStarLabelsChk"));
	}
	
	// -------------------------------------------------
	//	refreshDateTimeDisplay
	// -------------------------------------------------
	function refreshDateTimeDisplay(inSituation)
	{
		var theDate = inSituation.dateTime;
		var dateString = theDate.toDateString() // toLocaleFormat("%B %e, %Y");
		var mins = theDate.getMinutes();
		var secs = theDate.getSeconds();
		if (mins < 10) mins = "0"+mins;
		if( secs < 10) secs = "0"+secs;     
		var timeString = theDate.getHours() + ":" + mins + ":" + secs; //theDate.toLocaleFormat("%H:%M:%S");
		
		$("currentDateTime").innerHTML =  dateString + ' at ' + timeString;
	}
	
	// -------------------------------------------------
	//	imageRefreshed
	// -------------------------------------------------
	function imageRefreshed()
	{
		refreshDateTimeDisplay(SNWEBVIEW.situation);
	}
	// define our imageRefreshed callback so we get informed when a new image is shown
	SNWEBVIEW.imageRefreshed = imageRefreshed;
	
	
	// -------------------------------------------------
	//	setLocationNameUI
	// -------------------------------------------------
	function setLocationNameUI(inName)
	{
		$("currentLocation").innerHTML = inName;
		$("locationSearch").value = inName; // set this so that the user knows they found one
	}
	
	// -------------------------------------------------
	//	getTimeZoneLocationName
	// -------------------------------------------------
	function getTimeZoneLocationName(inSituation)
	{	
		var requestURL = SNWEB.getRequestURL({	type:		SNWEB.consts.kGetNearestCityRequest,
												situ:		inSituation});
	
		new Ajax.Request(requestURL.url, {method: 'post', parameters: requestURL.parameters, onFailure: getTimeZoneLocationNameFailure, onSuccess: locationNameTimeZoneSuccess});
	}
	
	// -------------------------------------------------
	//	getTimeZoneLocationNameFailure
	// -------------------------------------------------
	function getTimeZoneLocationNameFailure()
	{
		SNWEBVIEW.situation.location.name = "";
		$("currentLocation").innerHTML = SNWEBVIEW.situation.location.lat + " " + SNWEBVIEW.situation.location.lng;
	}
	
	// -------------------------------------------------
	//	locationNameTimeZoneSuccess
	// -------------------------------------------------
	function locationNameTimeZoneSuccess(transport)
	{
//		SNWEB.trackAction({action: SNWEB.consts.kTrack_NearestCityRequest});
	
		var replyFields = transport.responseText.split('|');
	
		SNWEBVIEW.situation.location.timezone = replyFields[1];
		
		SNWEBVIEW.situation.location.useDST = SNWEBVIEW.situation.currentlyExperiencingDST();
		setControlsToMatchSituation(SNWEBVIEW.situation);	// since the new location might be using DST
	
		SNWEBVIEW.situation.location.name = replyFields[0]; // name is not a default param of situation.location. I create it here 
		setLocationNameUI(SNWEBVIEW.situation.location.name); 
	
		gImageNeedsRefresh = true;
	}
	
	
	// -------------------------------------------------
	//	getLatLongFromAddress
	// -------------------------------------------------
	function getLatLongFromAddress()
	{
		(new GClientGeocoder()).getLatLng(String($("locationSearch").value), getLatLongCallback);
	}
	
	// -------------------------------------------------
	//	getLatLongCallback
	// -------------------------------------------------
	function getLatLongCallback(latLongPoint)
	{
		if (latLongPoint) {
//			SNWEB.trackAction({action: SNWEB.consts.kTrack_ZipPostalRequest});
		
			SNWEBVIEW.situation.location.lat	= latLongPoint.lat();
			SNWEBVIEW.situation.location.lng	= latLongPoint.lng();
				
			setControlsToMatchSituation(SNWEBVIEW.situation);	// since the new location might be using DST
			getTimeZoneLocationName(SNWEBVIEW.situation);
			
			gImageNeedsRefresh = true;	
		} else {
			$("locationSearch").value = "NOT FOUND!";
			setTimeout(clearLocationSearch, 1500);	
		}
	}
	
	// -------------------------------------------------
	//	clearLocationSearch
	// -------------------------------------------------
	function clearLocationSearch()
	{	
		$("locationSearch").value = "";
	}
	
	// -------------------------------------------------
	//	blurLocationLookup
	// -------------------------------------------------
	function blurLocationLookup(inEvt)
	{
		if (SNWEBVIEW.situation.location.name){
			$("locationSearch").value = SNWEBVIEW.situation.location.name;
		} else {
			$("locationSearch").value = '';
		}
	}
	
	// -------------------------------------------------
	//	locationLookupKeyPress
	// -------------------------------------------------
	function locationLookupKeyPress(inEvt)
	{
		// event handling boilerplate
		inEvt = inEvt || event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
	
		switch (inEvt.keyCode)
		{
			case 13: // return
			case 3:  // enter
				getLatLongFromAddress();
				break;
		}
	}
	
	
	// -------------------------------------------------
	//	optionsChanged
	// -------------------------------------------------
	function optionsChanged(inEvt)
	{
	/*
		// event handling boilerplate
		inEvt = inEvt || event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
	*/
	
		// refresh the prefs and situation from the controls
		setSituationToMatchControls(SNWEBVIEW.situation);
	
		gImageNeedsRefresh = true;
	}
	
	// -------------------------------------------------
	//	hideUI
	// -------------------------------------------------
	function hideUI()
	{
		Effect.Fade($("userInterface"));	
	}
	
	// -------------------------------------------------
	//	showUI
	// -------------------------------------------------
	function showUI()
	{
		Effect.Appear($("userInterface"));
	}
	
	/*
	// -------------------------------------------------
	//	openGoogleMapsApp
	// -------------------------------------------------
	function openGoogleMapsApp(inEvt)
	{
		// event handling boilerplate
		inEvt = inEvt || event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
		
		var zoomLevel = 8; // seems like a decent zoom level
		var latLong = new GLatLng(SNWEBVIEW.situation.location.lat, SNWEBVIEW.situation.location.lng);
		var url = "http://maps.google.com/maps?&ll=" + latLong.toUrlValue(4) + "&z=" + zoomLevel;
		window.open(url, "Viewing Location");
	}
	*/
	
	 //----------------------------------------------------------------------
	//	Class:	IPhoneSettings
	//
	//	Purpose:	
	//
	//	Date			Initials	Version		Comments
	//  ----------	---------	----------	---------------------------
	//	2008/01/12		DWW			2.0.0		New
	//
	//----------------------------------------------------------------------
	var IPhoneSettingsHelper = Class.create(
	{
		initialize: function(inParams)
		{
			this.onDone = inParams.onDone || null; // should be  hideSettings(); here!
		},
		hidePanel: function(panel)
		{
			//
			// Hide the panel and return it its original position. 
			//
			// I did not use Element.hide and Element.show because they generate a JS error when the display parameter is already set in css.
			// See: http://wiki.script.aculo.us/scriptaculous/show/Element.show
			//
			panel.style.display = "none";
			panel.style.left = "0"; // Moves the panel back to the zero position. If you leave it in place, even if it's not visible, it will still affect the scrolling.
			panel.style.top = "0";  //
		},
		panelIn: function(panelID, headerID)
		{
			//
			// To bring a panel in from the right.
			//

			function prepareForIn(panel) {
				// Prepares a panel to appear from the right.
				panel.style.left = "100%";		// Moves the panel to offscreen right
				panel.style.display = "block";  // Makes it visible
			}

			var panel = $(panelID);
			var header = $(headerID);
			
			new Effect.Parallel([ new Effect.Morph(panel, {style: 'left: 0%', sync: true }),		// Move the panel to the left 
					  			  new Effect.Opacity(header, { sync: true, to: 1.0, from: 0.0 })],
								{ duration: 0.5, beforeStart: function(){prepareForIn(panel);}});
		},	
		panelOut: function(panelID, headerID)
		{
			//
			// To move a panel back to the right and out of sight  
			//
			var panel = $(panelID);
			var header = $(headerID);
			var hidePanelLocal = this.hidePanel.bind(this); // binding issues
			
			new Effect.Parallel([ new Effect.Morph(panel, {style: 'left: 100%', sync: true }),		//Move the panel to the right
					  			  new Effect.Opacity(header, { sync: true, to: 0.0, from: 1.0 })],
								{duration: 0.5, afterFinish: function(){hidePanelLocal(panel);}});
		},	
		panelUp: function (panelID)
		{
			//
			// To bring a panel up from the bottom (header does not fade in).
			//
			function prepareForUp(panel) {
				// Prepares a panel to appear from below.
				panel.style.top = "100%";		// Moves the panel to offscreen below
				panel.style.display = "block";  // Makes it visible
			}

			var panel = $(panelID);
			new Effect.Morph(panel, {style: 'top: 0%', duration: 0.5, beforeStart: function(){prepareForUp(panel);}});				
		},	
		panelDown: function (panelID)
		{
			//
			// To move a panel back down and out of sight (header does not fade in).
			//
			var panel = $(panelID);
			var hidePanelLocal = this.hidePanel.bind(this); // binding issues
			new Effect.Morph(panel, {style: 'top: 100%', duration: 0.5, afterFinish: function(){hidePanelLocal(panel);}});				
		},	
		doneDown: function (panelID)
		{
			//
			// To send a panel down and out of sight, but after first hiding Settings.
			// This has the effect of taking the user right back to the main screen.
			//
			var panel = $(panelID);
			var settings = $("settings");
			var hidePanelLocal = this.hidePanel.bind(this); // binding issues
			new Effect.Morph(panel, {style: 'top: 100%', duration: 0.5, beforeStart: function(){hidePanelLocal(settings);}, afterFinish: function(){hidePanelLocal(panel);}});				
		
			if (this.onDone) {
				this.onDone();
			}
		}
	});
	/// create one here for use throughout
	var settingsHelper = new IPhoneSettingsHelper({onDone: hideSettings});
	
		
	// -------------------------------------------------
	//	hideSettings
	// -------------------------------------------------
	function hideSettings()
	{
		setSituationToMatchControls(SNWEBVIEW.situation);
		
		if (gImageNeedsRefresh) {
			SNWEBVIEW.refreshImage();
			gImageNeedsRefresh = false;
			// writePrefs(SNWEBVIEW.situation); // only write out pref onunload
		}
	}
	
	
	//
	//
	// TOGGLE SWITCH FUNCTIONS 
	// TOGGLE SWITCH FUNCTIONS 
	// TOGGLE SWITCH FUNCTIONS 
	// TOGGLE SWITCH FUNCTIONS 
	//
	//
	function setSwitch(s, posn)
	{
		// Sets the posn property for the switch, s. Also sets the initial static background.
		//
		// The moving background contains both ON and OFF for the toggle; but, since this graphic
		// contains bits on either side of the switch that we don't want to see when it's static, we switch to 
		// a static ON or OFF graphic when the movement is complete.
		//
		// All three of these graphics are contained in on-and-off.png and accessed by adjusting the position
		// of the background. Changing the actual background image is more straightforward, but resulted in flicker.
		//
		s.posn = !!posn; // !! ensures that the value will be interpreted as a boolean
		if (posn) {
			s.style.background = "url(http://www.starrynight.com/widget/iphone/img/on-and-off.png) 0 27px";
			}
		else {
			s.style.background = "url(http://www.starrynight.com/widget/iphone/img/on-and-off.png) -55px 54px";
			}
	}
	
	function getSwitch(s)
	{
		return s.posn;
	}
	
	
	function toggleSwitchHandler(inEvt)
	{	
		// event handling boilerplate
		inEvt = inEvt || window.event;
		var target = inEvt.target || inEvt.srcElement;	
		inEvt.cancelBubble = true;
		if (inEvt.stopPropogation) {
			inEvt.stopPropogation();
		}
	
		toggleSwitch(target.parentNode);
		optionsChanged();
	}
		
	function toggleSwitch(s)
	{	// Toggles the switch, s. The posn property of s is set in setSwitch().
		
		if (s.posn) { // If it's on...
			s.style.backgroundPosition = "0 0"; // Swap in the movable background in the ON position, move it, then set the switch to its new position
			new Effect.Morph (s, { style: 'background-position: -55px 0', duration: 0.1, afterFinish: function(){setSwitch(s, !s.posn)}});
		}
		else {
			s.style.backgroundPosition = "-55px 0"; // Swap in the movable background in the OFF position, move it, then set the switch to its new position
			new Effect.Morph (s, { style: 'background-position: 0 0', duration: 0.1, afterFinish: function(){setSwitch(s, !s.posn)}});
		}
	}
		
	function toggleDateDim()
	{
		if ($("dateDimmer").style.visibility == "hidden") {
			disableDateAndTime()
		}
		else {
			enableDateAndTime();
		}
	}
	
	//
	//
	// DATE DIMMER FUNCTIONS 
	// DATE DIMMER FUNCTIONS 
	// DATE DIMMER FUNCTIONS 
	// DATE DIMMER FUNCTIONS 
	//
	//
	function enableDateAndTime()
	{ 						
		// Hides a translucent cover over the date and time controls
		$("dateDimmer").style.visibility = "hidden";	// which effectively enables them.
		$("timeDimmer").style.visibility = "hidden";
		$("DSTDimmer").style.visibility = "hidden";
	}
		
	function disableDateAndTime()
	{ 					
		// Reveals a translucent cover over the date and time controls
		$("dateDimmer").style.visibility = "inherit";	// which dims them and effectively disables them.
		$("timeDimmer").style.visibility = "inherit";	// Note: I use inherit instead of visible, otherwise they may remain visible
		$("DSTDimmer").style.visibility = "inherit";	// even after the panel is hidden.
	}
	
	function setMonthPadding()
	{
		var monthPadding = [ "109px", // January    These were all carefully determined by adding a space and a two digit date
							"101px", // February    to the end of each month <option> and so letting it overlap with that
							"122px", // March       same number in the date field. These needs to be finalized on the iPhone
							"135px", // April       since the font metric appear to differ slightly from those on Safari desktop.
							"137px", // May
							"133px", // June
							"139px", // July
							"117px", // August
							"86px", // September
							"109px", // October
							"91px", // November
							"91px"]; // December
							
		// Adjust the padding of the MONTH pop-up to the month text in the pop-up
		m = $("monthPopup");  
		m.style.borderLeftWidth = monthPadding[m.selectedIndex];
			
		if (window.innerWidth == 480) {
			m.style.borderLeftWidth = parseInt(m.style.borderLeftWidth) + 160 + "px"
			}
	
		d = $("dayPopup");
		if (d.value < 10) {
			m.style.borderLeftWidth = parseInt(m.style.borderLeftWidth) + 9 + "px"
			}
	}
		
	function setDayWidth()
	{	
		// Adjust the right position of the DAY pop-up to right justify one and two digit numbers.
		d = $("dayPopup");
		if (d.value > 9) {
			d.style.right = "92px"
			}
		else {
			d.style.right = "83px"
			}
		setMonthPadding(); // Re-adjust the position of the month, since it will need to be changed if the date width has changed.
	}
		
	function setHoursPadding()
	{	// Adjust the width of the HOURS pop-up to right justify one and two digit numbers.
		h = $("hoursPopup");
		if (h.value > 9) {
			h.style.borderLeftWidth = "164px"
			}
		else {
			h.style.borderLeftWidth = "173px"
			}
		if (window.innerWidth == 480) {
			h.style.borderLeftWidth = parseInt(h.style.borderLeftWidth) + 160 + "px"
			}
	}
	
	function handleOrientationChange()
	{
		//
		// Pushes the address bar up and out of sight.
		// For this to work, the height of the content needs to be at least the size of the screen,
		// so I set .panel-content to be the height of the window by adding a style to the beginning of the list.
		
		if (document.styleSheets[0].cssRules[0].selectorText == ".panel-content") { // If I've already added the rule, remove it.
			document.styleSheets[0].deleteRule(0);									// Otherwise the new rule added next will be over-ridden
			}																		// by the the last one I added.
		
	
		setMonthPadding(); // The <select> padding hack requires this to be reset whenever the width changes
		setHoursPadding(); // The hack uses window.InnerWidth to set the padding.
			
		// this cleans up the SN sky view orientation
		updateOrientation();
		
		// Add the new style to the beginning of the list. Without the Timeout, window.innerHeight doesn't register correctly.
		setTimeout("document.styleSheets[0].insertRule('.panel-content {min-height: ' + (window.innerHeight) + 'px;}', 0);", 0)
		// Push the address bar out of sight
		setTimeout(function(){window.scrollTo(0,1);}, 0)
	}
	
	// -------------------------------------------------
	//	updateOrientation
	// -------------------------------------------------
	function updateOrientation()
	{
		var snInPortrait = isSNInPortrait();
		var iPodInPortrait = true;
		
		switch(window.orientation)
		{	
			case 0:
				iPodInPortrait = true;
				break; // portrait
			case 180:
				iPodInPortrait = true;
				break; // "Portrait (upside-down portrait)"
			case -90:
				iPodInPortrait = false;
				break; //"Landscape (right, screen turned clockwise)";
			case 90:
				iPodInPortrait = false;
				break; // "Landscape (left, screen turned counterclockwise)"
		}
	
		if (iPodInPortrait && !snInPortrait)
		{
			console.log("iPod: " + window.orientation);
			console.log("portrait");
			setToPortrait();
		}
		else if (!iPodInPortrait && snInPortrait)
		{
			console.log("iPod: " + window.orientation);
			console.log("landscape");
			setToLandscape();
		}
	}
	
	// -------------------------------------------------
	//	addEventHandlers
	// -------------------------------------------------
	function addEventHandlers()
	{
		function addEventHandlerToElementsWithClass(inEventType, inClassName, inHandler)
		{
			var theElemsArray = SNWEB.utils.getElementsByClassName(inClassName);
			var i = 0;
			for (i = 0; i < theElemsArray.length; i += 1)
			{
				Event.observe(theElemsArray[i], inEventType, inHandler);
			}
		}
	
		// Add handlers for classes
		addEventHandlerToElementsWithClass('click',		'toggleHighlight',	toggleSwitchHandler);
		addEventHandlerToElementsWithClass('change',	'snoption',			optionsChanged);
			
		// add an additional click handler for the current time toggler
		Event.observe($('currentTimeToggler'), 'click', toggleDateDim);	
	
		// date changes
		Event.observe($('monthPopup'), 'change', monthChanged);	
		Event.observe($('dayPopup'), 'change', setDayWidth);	
		Event.observe($('yearPopup'), 'change', setMonthPadding);
		
		// time changes
		Event.observe($('hoursPopup'), 'change', setHoursPadding);
	
		// SHOW THE SETTINGS!
		$('settingsButton').onclick = function() {settingsHelper.panelUp('settings');};
		
		// home view
		Event.observe($('homeViewButton'), 'click', homeView);
	
		// The location search field needs a few things
		var locationSearchBox = $("locationSearch");
		locationSearchBox.onkeypress = locationLookupKeyPress; // this is really just for testing in a browser, since iPhone won't get the enter or return for this.
		locationSearchBox.onfocus = clearLocationSearch;
		locationSearchBox.onblur = blurLocationLookup;
	}
	
	
	// -------------------------------------------------
	//	loadApp
	// -------------------------------------------------
	function loadApp()
	{	
		// create a situation here so that we can read the prefs into it before showing the first image
		var situation = new SNWEB.SNSituation();
		situation.gaze.alt = kDefaultMobileAlt; // this looks nicer
		
		// read in any prefs
		readPrefs(situation);
	
		// do this so it works on any server including dev!
		SNWEB.consts.kServerCGI = "/widget/snclient.php?";
		
		// this call searches for any DIV with the class "snSkyView" and injects the necessary HTML into it
		SNWEBVIEW.init({platform: SNWEB.consts.kAppleMobile,
						version: "1.0",
						panning: false,
						zooming: false,
						cardinals: false,
						flowingTime: true,
						advert: {frequency: 100, showAdMilliseconds: 500, beforeAdShow: hideUI, afterAdHide: showUI, bgCSS: "white"},
						situation: situation});
		
		// add additional event handlers
		addEventHandlers();
	
		// populate the days separately from setting the value
		populateDaysPopup(SNWEBVIEW.situation);
		populateYearsPopup(SNWEBVIEW.situation);
		
		setControlsToMatchSituation(SNWEBVIEW.situation);
		 
		getTimeZoneLocationName(SNWEBVIEW.situation); // 
		refreshDateTimeDisplay(SNWEBVIEW.situation);
	
		handleOrientationChange();
	}
	
	// -------------------------------------------------
	//	unloadApp
	// -------------------------------------------------
	function unloadApp()
	{
		writePrefs(SNWEBVIEW.situation);
		GUnload(); // this ensures that google maps doesn't leak
	}
	
	var returnObject = [];
	returnObject.initialize = function () {loadApp();};
	returnObject.savePrefs = function () {unloadApp();};
	returnObject.orientationChange = function () {handleOrientationChange();};
	returnObject.settings = settingsHelper;
	returnObject.getLatLongFromAddress = function() {getLatLongFromAddress();};
	return returnObject;
})();
