
//Implied globals for JSLint
// From Tips
/*globals ABOVE, BALLOON, BALLOONSTEMOFFSET, OFFSETX, Tip, UnTip */

//From Google Maps
/*globals GBrowserIsCompatible, GEvent, GIcon, GLargeMapControl, GLatLng, GMap2, GMarker, GPoint, GScaleControl, GSize, GStreetviewPanorama */

// NYCVP
/*globals DHTMLSuite, GUnload, loadRockefellerPoly, loadSubways, loadTimeSquare, hotels, sights, markerOptions, restaurants, theaters */


// GLOBAL VARIABLES
//==============================================

var NYCVPObjectArray = new Array();

var LegendInstructions = '<p><b>How to Use this Map</b><p>' +
						 '<p>Each Tab above represents one of the options: Hotels, Theaters, etc. ' +
						 'When you select one of those options this Legend will appear. You can ' +
						 'then click on the item in the legend and the map will center on that ' +
						 'selection. It will then flash momentarily so that you can identify the ' +
						 'location.</p>' +
						 '<p>If you roll your mouse over a marker it will identify the location. ' +
						 'When indicated you can click on the marker for additional details about ' +
						 'the location.</p>' +
						 '<p>You can also see the &quot;<b>Street View</b>&quot; of some location. First ' +
						 'click you mouse on marker for the location of interest or select the item from ' +
						 'the list in the Legend. The &quot;<b>Street View</b>&quot; will now be centered ' +
						 'on that area in the city.</p>' +
						 '<p>We hope you enjoy and find the information provided here of value for your ' +
						 'trip to New York.</p>';

var timerInterval = 0 ; //handle of javascript .setInterval
var times2Flash; //number of times to flash on/off
var flashingMarker;

// for testing in locations other then a root application path
//var baseURL = "http://localhost/nyctrip/trunk/";
var baseURL = "/";
var map;
var myPano;
var lastPanLatLong;
var legendWindow;
var panoWindow;
var infoWindow;

// END GLOBAL VARIABLES
//=======================================


// Base foundation object class
//=======================================
						 					 
function createNewArray(arrayName)
{
	var newArray = new Array();
	NYCVPObjectArray[arrayName] = newArray;
//	NYCVPObjectArray[objCounter] = newArray;
//	objCounter++;
	return newArray;
}

function NYCVPMapObjectClass(name, Lat, Long)
{
	this.name = name;
	this.Lat = Lat;
	this.Long = Long;
	this.desc = "Not available";
	this.markerColor = "red";
	this.swapShadowColor = false;
	this.overlay = null;
	this.polyOverlay = null;
	this.currentState = 0;
	this.legend = false;
	this.legendTab = "";
}

NYCVPMapObjectClass.prototype.display = function()
{
	var popupObj;
	
	popupObj = document.getElementById('popupContent');
	
	popupObj.innerHTML = this.desc;
	
	infoWindow.show();
};

NYCVPMapObjectClass.prototype.tip = function()
{
	Tip('<b>' + this.name + '</b><br/>Click on the marker for details.', BALLOON, true, ABOVE, true, OFFSETX, -25, BALLOONSTEMOFFSET, -5);
};

// it is assumed that the [0] element of the object array will contain the toggle state
// of all objects in the array.
NYCVPMapObjectClass.prototype.toggle = function()
{
	if (this.currentState === 0)
	{
		this.currentState = 1;
	}
	else
	{
		this.currentState = 0;
	}
		
	return this.currentState;
};

Function.prototype.DeriveFrom = function (fnSuper)
{
    var prop;
	
    if (this == fnSuper)
	{
        alert("Error - cannot derive from self");
        return;
    }
	
    for (prop in fnSuper.prototype)
	{
        if (typeof fnSuper.prototype[prop] == "function" && !this.prototype[prop])
		{
            this.prototype[prop] = fnSuper.prototype[prop];
        }
    }

    this.prototype[fnSuper.StName()] = fnSuper;
};

Function.prototype.StName = function ()
{
    var st;
	
    st = this.toString();
    st = st.substring(st.indexOf(" ") + 1, st.indexOf("("));
	
    if (st.charAt(0) == "(")
	{
        st = "function ...";
    }
	
    return st;
};

Function.prototype.Override = function (fnSuper, stMethod)
{
    this.prototype[fnSuper.StName() + "_" + stMethod] = fnSuper.prototype[stMethod];
};

// END CLASS Definition
//=======================================


// Basic Utilities and tools for Google Maps
//===================================

	function handleNoFlash(errorCode)
	{
		// only show the error if the panorama window is actually open.
		if (document.getElementById('StreetView').checked)
		{
			if (errorCode == 603)
			{
				alert("Error: Flash doesn't appear to be supported by your browser");
				return;
			}
			if (errorCode == 600)
			{
				alert("I'm sorry but there is no nearby \"Street View\" for this location.");
				return;
			}
		}
	}  
	
	function showPano(Lat, Long)
	{
		lastPanLatLong = new GLatLng(Lat, Long);
		if (document.getElementById('StreetView').checked)
		{
			myPano.setLocationAndPOV(lastPanLatLong);
		}
	}

	// if the panorama window closes make sure it turns off the street view Checkbox. This is the callback function from the object
	function panoClosed()
	{
		document.getElementById('StreetView').checked=false;
	}
	
	function centerMap(Lat, Long, zoom, dopan)
	{
		if (typeof dopan == 'undefined' )
		{
			dopan = true;
		}
		
		map.setCenter(new GLatLng(Lat,Long), zoom);
		
		if (dopan)
		{
			showPano(Lat, Long);
		}
	}
	
	function setCBs2Default()
	{
		// make sure checkboxes are all off at start.
		document.getElementById('HotelsCB').checked=false;
		document.getElementById('RestaurantsCB').checked=false;
		document.getElementById('TheatersCB').checked=false;
		document.getElementById('SightsCB').checked=false;
		document.getElementById('MiscCB').checked=false;
		document.getElementById('SubwaysCB').checked=false;
		document.getElementById('TimesSqCB').checked=false;
		document.getElementById('StreetView').checked=false;
	}

	function createLegendLinks(objectArrayName)
	{
		var obj;
		var index;
		var linksList;
		var counter;
		var latlong;
		var objectArray;
		linksList = '';

		objectArray = NYCVPObjectArray[objectArrayName];
		
		for (index in objectArray)
		{
			obj = objectArray[index];
			latlong = obj.Lat + ',' + obj.Long + ',17';
			counter = parseInt(index, 10) + 1;
			linksList += '<span class="legendLink" onmouseover="legendLinkHighlight(this,true);" onmouseout="legendLinkHighlight(this,false);" onclick="centerMap(' + latlong + '); markerIndicator(\'' + objectArrayName + '\',' + index + ');">' + (parseInt(index, 10) + 1) + '. ' + obj.name + '</span><br/>';
		}
		
		return linksList;
	}
	
	function generateWindows()
	{
		DHTMLSuite.commonObj.setCssCacheStatus(false);

		var windowModel = new DHTMLSuite.windowModel({windowsTheme:true, id:'legendWindowModel', title:'Legends', isVisible:false, isRresizable:true, isClosable:false, maxWidth:400, isDragable:true, xPos:470, yPos:40, width:300, height:350, minWidth:250, minHeight:300 } ); 	
		windowModel.addTab({ id:'legendTab0', tabTitle:'Instructions', textContent: '<div style="padding: 4px;">' + LegendInstructions + '</div>'} ); 	
		windowModel.addTab({ id:'legendTab1', tabTitle:'Hotels', textContent:'<img src="../_images/nycvpred.png" width="11px" height="17px" border="0"/> - Red Markers<br />' + createLegendLinks('hotels')} ); 	
		windowModel.addTab({ id:'legendTab2', tabTitle:'Restaurants', textContent:'<img src="../_images/nycvpyellow.png" width="11px" height="17px" border="0"/> - Yellow Markers<br />' + createLegendLinks('restaurants')} ); 	
		windowModel.addTab({ id:'legendTab3', tabTitle:'Theaters', textContent:'<img src="../_images/nycvpblue.png" width="11px" height="17px" border="0"/> - Blue Markers<br />' + createLegendLinks('theaters')} ); 	
		windowModel.addTab({ id:'legendTab4', tabTitle:'Sightseeing', textContent:'<img src="../_images/nycvpgreen.png" width="11px" height="17px" border="0"/> - Green Markers<br />' + createLegendLinks('sights')} ); 	
		windowModel.addTab({ id:'legendTab5', tabTitle:'Misc', textContent:'<img src="../_images/nycvppurple.png" width="11px" height="17px" border="0"/> - Purple Markers<br />' + createLegendLinks('miscellaneous')} ); 	
		
		legendWindow = new DHTMLSuite.windowWidget();
		legendWindow.setLayoutOffsetHeightForTheStatusBar(1);
		legendWindow.setLayoutCss('window-theme-windows.css');
		legendWindow.addWindowModel(windowModel);
		legendWindow.init();

		var windowModel2 = new DHTMLSuite.windowModel({windowsTheme:true, id:'panoWindowModel', title:'Street View', isMinimizable:false, isVisible:false, isResizable:false, isClosable:true, width:382, height:306, isDragable:true, xPos:300, yPos:200, callbackOnClose:'panoClosed' } ); 	
		windowModel2.addTab({ id:'panoTab0', htmlElementId:'panoTab0',tabTitle:'Panorama', textContent:'<div name="panoDiv" id="panoDiv" style="width:380px; height:255px;"></div>'} ); 	
		
		panoWindow = new DHTMLSuite.windowWidget();
		panoWindow.setLayoutOffsetHeightForTheStatusBar(1);
		panoWindow.setLayoutCss('window-theme-windows.css');
		panoWindow.addWindowModel(windowModel2);
		panoWindow.init();
		
		var windowModel3 = new DHTMLSuite.windowModel({windowsTheme:true, id:'infoWindowModel', title:'Information', isMinimizable:false, isVisible:false, isResizable:true, isClosable:true, maxWidth:700, maxHeight:500, isDragable:true, xPos:50, yPos:100, width:630, height:350, minWidth:630, minHeight:300 } ); 	
		windowModel3.addTab({ id:'infoTab0', htmlElementId:'infoTab0',tabTitle:'Details', textContent:'<div name="popupContent" id="popupContent" style="background-color: #FFFFFF;"></div>'} ); 	
		
		infoWindow = new DHTMLSuite.windowWidget();
		infoWindow.setLayoutOffsetHeightForTheStatusBar(1);
		infoWindow.setLayoutCss('window-theme-windows.css');
		infoWindow.addWindowModel(windowModel3);
		infoWindow.init();

		var myWindowCollection = new DHTMLSuite.windowCollection();
		myWindowCollection.addWindow(legendWindow);
		myWindowCollection.addWindow(panoWindow);
		myWindowCollection.addWindow(infoWindow);
		myWindowCollection.setNumberOfColumnsWhenTiled(1);
		myWindowCollection.setDivWindowsArea('mapWindowArea');
	}

	function createMarker(obj, index, descLink)
	{
		var imageURL;
		var baseIcon = new GIcon();
		
		baseIcon.shadow = baseURL + "_images/shadow50.png";
		baseIcon.iconSize = new GSize(22, 35);
		baseIcon.shadowSize = new GSize(37, 34);
		baseIcon.iconAnchor = new GPoint(9, 34);
		baseIcon.infoWindowAnchor = new GPoint(9, 2);
		baseIcon.infoShadowAnchor = new GPoint(18, 25);
			
		var letter = String.fromCharCode('A'.charCodeAt(0) + index);
		var letteredIcon = new GIcon(baseIcon);

		imageURL = baseURL + "pages/markers.aspx?ndx=" + (index + 1) + "&color=" + obj.markerColor;
		if (obj.swapShadowColor)
		{
			imageURL += "&sc=true";
		}
		
		// adding .png to the end of the URL to fake out the Google Javascript code and let it know that this image really is a png
		imageURL += "&bogus=.png";
		letteredIcon.image = imageURL;
		markerOptions = { icon:letteredIcon };
		var latlong = new GLatLng(obj.Lat, obj.Long);
		var marker = new GMarker(latlong, markerOptions);
		if (descLink === true)
		{
			GEvent.addListener(marker, 'click', function() {obj.display();});
		}
		GEvent.addListener(marker, 'mouseover', function() {obj.tip();});
		GEvent.addListener(marker, 'mouseout', function() {UnTip();});
		return marker;
	}

	function loadMapObjects(objectArray, map, descLink)
	{
		var obj;
		var index;
		if (typeof descLink == 'undefined' )
		{
			descLink = true;
		}
		
		for (index in objectArray)
		{
			obj = objectArray[index];
			obj.overlay = createMarker(obj, parseInt(index, 10), descLink);
		}
	}
	
	function GmapLoad()
	{
		generateWindows();
		setCBs2Default();
		myPano = null;

		if (GBrowserIsCompatible())
		{

			map = new GMap2(document.getElementById("map"));

			loadSubways();
			loadTimeSquare();
			loadMapObjects(hotels, map);
			loadMapObjects(restaurants, map);
			loadMapObjects(theaters, map, false);
			loadMapObjects(sights, map, false);
			loadMapObjects(miscs, map, false);
			// this should be part of the LoadMapObjects but we don't have the time to code it right now.
			loadRockefellerPoly();

			map.addControl(new GScaleControl());
			map.addControl(new GLargeMapControl());
			
			myPano = new GStreetviewPanorama(document.getElementById("panoDiv"));
			GEvent.addListener(myPano, "error", handleNoFlash);

			centerMap(40.758083, -73.984723, 13);
		}
	}

	// this returns the true or false dependent on those check boxes that control markers
	function anyChecked()
	{
		var returnValue = false;
		
		if (document.getElementById('HotelsCB').checked)
		{
			returnValue = true;
		}
		
		if (document.getElementById('SubwaysCB').checked)
		{
			returnValue = true;
		}
		
		if (document.getElementById('SightsCB').checked)
		{
			returnValue = true;
		}
		
		if (document.getElementById('RestaurantsCB').checked)
		{
			returnValue = true;
		}
		
		if (document.getElementById('TheatersCB').checked)
		{
			returnValue = true;
		}
		
		if (document.getElementById('MiscCB').checked)
		{
			returnValue = true;
		}
		
		return returnValue;
	}

	function toggleLegend()
	{
		var objArray;
		var index;
		var state;
		var usesLegend;
		var stateCount = 0;
		var firstVisibleTab = "";
		
		for (index in NYCVPObjectArray)
		{
			objArray = NYCVPObjectArray[index];
			state = objArray[0].currentState;
			usesLegend = objArray[0].legend;
			if (usesLegend)
			{
				if (state == 1)
					{
						stateCount++;
						legendWindow.restoreTab(objArray[0].legendTab);
						if (firstVisibleTab === "")
						{
							firstVisibleTab = objArray[0].legendTab;
						}
					}
					else
					{
						legendWindow.deleteTab(objArray[0].legendTab);
					}
			}
		}
		if (usesLegend)
		{
			if (stateCount === 0)
			{
				legendWindow.close();
			}
			else
			{
				legendWindow.show();
				legendWindow.activateTab(firstVisibleTab);
			}
		}
	}
	
	function toggleOverlays(objectArray)
	{
		var obj;
		var index;
		var state;

		// this toggles the current state value and returns what the new state should be.
		state = objectArray[0].toggle();
		
		for (index in objectArray)
		{
			obj = objectArray[index];
			if (state === 0)
			{
				map.removeOverlay(obj.overlay);
				if (obj.polyOverlay !== null)
				{
					map.removeOverlay(obj.polyOverlay);
				}
				
			}
			else
			{
				map.addOverlay(obj.overlay);
				if (obj.polyOverlay !== null)
				{
					map.addOverlay(obj.polyOverlay);
				}
			}
		}

		toggleLegend();
	}

	function toggleStreetView(state)
	{
		if (state === true)
		{
			panoWindow.show();
			if (myPano !== null)
			{
				myPano.remove();
			}
			// if no check boxes selected then go to Times Sq.
			if (anyChecked() === false)
			{
				lastPanLatLong = new GLatLng(40.75827778801546, -73.9854097366333);
			}
			myPano = new GStreetviewPanorama(document.getElementById("panoDiv"));
			GEvent.addListener(myPano, "error", handleNoFlash);
			myPano.setLocationAndPOV(lastPanLatLong);
		}
		else
			{
			myPano.remove();
			myPano = null;
			panoWindow.close();
			}
	}
	
	function markerIndicator(objectArrayName, index)
	{
		var objectArray;

		objectArray = NYCVPObjectArray[objectArrayName];

		flashingMarker = objectArray[index].overlay;
		
		/*
		 invoke neOn via setTimeout - initial delay is set to 1200 ms (your choice)
		 to allow map to redraw, whatever
		 set im = number of times to flash on/off
		*/
		// i.e. don't do if prev sequence still active
		if (timerInterval === 0)
		{
		  times2Flash = 16;
		  window.setTimeout('flashMarker()', 1200);
		}
	}

	function flashMarker()
	{
		// flash marker by invoking this function every 200ms (whatever)
		// each time, decrement counter im, until < 0
		if (times2Flash-- % 2 == 1)
		{
			flashingMarker.hide();
		}
		else
		{
			flashingMarker.show();
		}

		if (timerInterval === 0)
		{
			// ix is handle to an instance of setInterval: zero when not initialised
			timerInterval = window.setInterval('flashMarker()', 200);
		}
		else
		{
			if (times2Flash < 0)
			{
				window.clearInterval(timerInterval);
				timerInterval = 0;
				// make sure it ends being turned on
				flashingMarker.show();
			}
		}
	} 

	function legendLinkHighlight(obj, state)
	{
		if (state === true)
		{
//			obj.style.color='#FFCC60';
			obj.style.color='#FF0000';
		}
		else
		{
			obj.style.color='#185596';
		}
	}

	function MapInit()
	{
		if (window.addEventListener) //run onload in DOM2 browsers
		{
			window.addEventListener("load", GmapLoad, false);
		}
		else if (window.attachEvent) //run onload in IE5.5+
		{
			window.attachEvent("onload", GmapLoad);
		}

		if (window.addEventListener) //run onunload in DOM2 browsers
		{
			window.addEventListener("unload", GUnload, false);
		}
		else if (window.attachEvent) //run onload in IE5.5+
		{
			window.attachEvent("onunload", GUnload);
		}
	}