Import.namespace('rnw.expat');

/**
 *	Application
 *	@package	rnw.expat
 *	@uses		frame.core.Delegate
 *	@author		Maarten Dieleman <maarten@bloodyorange.com>
**/
	/**
	 *	constructor
	 *	
	 *	@access		public
	 *	@param		void
	 *	@return		object
	**/
	rnw.expat.Application = function()
	{
		if (undefined === GMap2) return; // for development purposes only
		
		window.onSpreadsheetLoad			= Delegate.create(this, this.onSpreadsheetLoad);
		window.closeInfoWindow				= Delegate.create(this, this.closeInfoWindow);
		window.onRecentFilterClick			= Delegate.create(this, this.onRecentFilterClick);
		window.setCenter					= Delegate.create(this, this.setCenter);
		
		GEvent.addDomListener(document, 'mousemove', Delegate.create(this, this.onMouseMove));
		
		this.intMouseX						= 0;
		this.intMouseY						= 0;
		
		this.objMap							= undefined;
		this.objInfoWindow					= undefined;
		this.objLargeMapControl				= undefined;
		this.arrMarkers						= new Array();
		this.arrFilters						= new Array();
		this.blnShowRecent					= true;
		
		this.objBaseIcon					= new GIcon();
		this.objBaseIcon.shadow				= './images/markers/shadow.png';
		this.objBaseIcon.iconSize			= new GSize(16, 26);
		this.objBaseIcon.shadowSize			= new GSize(35, 19);
		this.objBaseIcon.iconAnchor			= new GPoint(8, 25);
		this.objBaseIcon.infoWindowAnchor	= new GPoint(9, 2);
		this.objBaseIcon.infoShadowAnchor	= new GPoint(18, 25);
		
		//this.strRssUrl						= 'http://www.google.com/reader/public/atom/user/11476672216952104757/label/zomerselectie';
		//this.strRssUrl						= './rss.xml';
		//this.strRssUrl						= './rssproxy.php';
		this.strRssUrl						= './rss/files/links.txt';
		
		this.sheet			= 
		{
			wsId			: 'od6',
			ssKey			: 'pdpEg7KACdGu9XNYMTwlZOQ'
		};
		this.sheet.column	= 
		{
			title			: 'gsx$titel',
			link			: 'gsx$link',
			description		: 'gsx$omschrijving',
			lat				: 'gsx$lat',
			lng				: 'gsx$long',
			rank			: 'gsx$rank',
			type			: 'gsx$soort',
			picture			: 'gsx$picture',
			city			: 'gsx$plaats',
			country			: 'gsx$land'
		};
		
		this.init();
	}
	
	/**
	 *	init
	 *	Loads map and calls function to load in worksheet data
	 *	
	 *	@access		private
	 *	@param		void
	 *	@return		void
	**/
	rnw.expat.Application.prototype.init = function()
	{
		if (GBrowserIsCompatible())
		{
			this.objLargeMapControl = new rnw.expat.controls.LargeMapControl();
			
			this.objMap = new GMap2(document.getElementById('map'));
			this.objMap.addControl(this.objLargeMapControl, new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(15, 36)));
			this.objMap.addControl(new rnw.expat.controls.MapTypeControl(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(15, 12)));
			this.objMap.setCenter(new GLatLng(43.907787, -79.359741), 2);
			
			var objPos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0, 0));
			objPos.apply(document.getElementById('main_control'));
			this.objMap.getContainer().appendChild(document.getElementById('main_control'));
			
			var objPos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(0, 0));
			objPos.apply(document.getElementById('filter_control'));
			this.objMap.getContainer().appendChild(document.getElementById('filter_control'));
			
			window.map = this.objMap;
			
			this.loadSpreadsheet();
		}
		else
		{
			alert('Sorry, the Google Maps API is not compatible with this browser');
		}
	}
	
	/**
	 *	loadSpreadsheet
	 *	Creates a script tag in the page that loads in the
	 *	JSON feed for the specified key/ID
	 *	Once loaded, it calls onSpreadsheetLoad
	 *	
	 *	@access		private
	 *	@param		void
	 *	@return		void
	**/
	rnw.expat.Application.prototype.loadSpreadsheet = function()
	{
		var objScript	= document.createElement('script');
		objScript.type	= 'text/javascript';
		objScript.src	= 'http://spreadsheets.google.com/feeds/list/' + this.sheet.ssKey + '/' + this.sheet.wsId + '/public/values?alt=json-in-script&callback=onSpreadsheetLoad';
		
		document.getElementsByTagName('head')[0].appendChild(objScript);
	}
	
	/**
	 *	onSpreadsheetLoad
	 *	Called when JSON is loaded.
	 *	
	 *	@access		private
	 *	@param		ojbect		argObjData		spreadsheet data
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onSpreadsheetLoad = function(argObjData)
	{
		var objDiv = document.getElementById('loader');
		objDiv.parentNode.removeChild(objDiv);
		
		//argObjData.feed.entry.sort(Delegate.create(this, this.sortRows));
		
		var intRowCnt = argObjData.feed.entry.length;
		for (var i = 0; i < intRowCnt; i++)
		{
			var objRow = argObjData.feed.entry[i];
			if (undefined !== objRow[this.sheet.column.lat])
			{
				var objMarker = this.createMarker(objRow);
				this.objMap.addOverlay(objMarker);
				if ('blog' !== objRow[this.sheet.column.type].$t) objMarker.hide();
				
				this.arrMarkers.push(objMarker);
			}
		}
		
		this.loadRss();
	}
	
	/**
	 *	sortRows
	 *	Function that sorts 2 worksheet rows from JSON feed
	 *	based on their rank column. Only called if column is defined
	 *	
	 *	@access		private
	 *	@param		object		rowA	Represents row in JSON feed
	 *	@param		object		rowB	Represents row in JSON feed
	 *	@return		float		Difference between row values
	**/
	rnw.expat.Application.prototype.sortRows = function(rowA, rowB)
	{
		var rowAValue = parseFloat(rowA[this.sheet.column.rank].$t);
		var rowBValue = parseFloat(rowB[this.sheet.column.rank].$t);
		
		return rowAValue - rowBValue;
	}
	
	/**
	 *	onMouseMove
	 *	
	 *	@access		private
	 *	@param		object		argObjEvent
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onMouseMove = function(argObjEvent)
	{
		this.intMouseX = argObjEvent.clientX;
		this.intMouseY = argObjEvent.clientY;
	}
	
	/**
	 *	createMarker
	 *	
	 *	@access		private
	 *	@param		object		argObjRow
	 *	@return		GMarker		Marker created
	**/
	rnw.expat.Application.prototype.createMarker = function(argObjRow)
	{
		var strHtml		= '<div class="title">' + argObjRow[this.sheet.column.title].$t + '<a class="" href="#" onclick="return window.closeInfoWindow();"></a></div>';
		strHtml			+= '<div class="location">' + argObjRow[this.sheet.column.city].$t + ', ' + argObjRow[this.sheet.column.country].$t + '</div>';
		strHtml			+= '<div class="content">';
		var strType		= '';
		if (undefined !== argObjRow[this.sheet.column.type])
		{
			strType = argObjRow[this.sheet.column.type].$t;
			
			if (undefined === this.arrFilters[strType] && '' !== strType)
			{
				this.createFilter(strType);
				this.arrFilters[strType] = true;
			}
		}
		if (undefined !== argObjRow[this.sheet.column.picture])
		{
			strHtml += '<div class="image">' + argObjRow[this.sheet.column.picture].$t + '</div>';
		}
		if (undefined !== argObjRow[this.sheet.column.description])
		{
			strHtml += '<div class="description">' + argObjRow[this.sheet.column.description].$t + '</div>';
		}
		if (undefined !== argObjRow[this.sheet.column.link])
		{
			strHtml += '<div class="link">' + argObjRow[this.sheet.column.link].$t + '</div>';
		}
		strHtml += '</div>';
		
		var objIcon			= new GIcon(this.objBaseIcon);
		objIcon.imageOut	= './images/markers/' + strType + '.png';
		objIcon.imageOver	= './images/markers/' + strType + '.png';
		objIcon.image		= objIcon.imageOut;
		
		var objOptions		= new Object();
		objOptions.icon		= objIcon;
		objOptions.title	= argObjRow[this.sheet.column.title].$t;
		
		var lat				= argObjRow[this.sheet.column.lat].$t.split(',').join('.');
		var lng				= argObjRow[this.sheet.column.lng].$t.split(',').join('.');
		var objLatLng		= new GLatLng(lat, lng);
		
		var objMarker		= new GMarker(objLatLng, objOptions);
		objMarker.strType	= strType;
		objMarker.strHtml	= strHtml;
		objMarker.strLink	= argObjRow[this.sheet.column.link].$t;
		objMarker.blnRecent	= false;
		
		GEvent.addListener(objMarker, 'mouseover', function()
		{
			objMarker.setImage(objMarker.getIcon().imageOver);
		});
		GEvent.addListener(objMarker, 'mouseout', function()
		{
			objMarker.setImage(objMarker.getIcon().imageOut);
		});
		
		GEvent.addListener(objMarker, 'click', Delegate.create(this, function()
		{
			this.closeInfoWindow();
			this.objInfoWindow = new rnw.expat.overlays.InfoWindow(objMarker, objMarker.strHtml, this.intMouseX, this.intMouseY);
			this.objMap.addOverlay(this.objInfoWindow);
		}));
		
		return objMarker;
	}
	
	/**
	 *	closeInfoWindow
	 *	
	 *	@access		public
	 *	@param		void
	 *	@return		boolean
	**/
	rnw.expat.Application.prototype.closeInfoWindow = function()
	{
		if (undefined === this.objInfoWindow) return false;
		
		this.objInfoWindow.remove();
		this.objInfoWindow = undefined;
		
		return false;
	}
	
	/**
	 *	createFilter
	 *	
	 *	@access		private
	 *	@param		string		argStrType
	 *	@return		void
	**/
	rnw.expat.Application.prototype.createFilter = function(argStrType)
	{
		var objCheckbox		= document.createElement('input');
		objCheckbox.type	= 'checkbox';
		objCheckbox.onclick	= Delegate.create(this, this.onFilterClick, objCheckbox, argStrType);
		
		var objSpan			= document.createElement('span');
		var strText			= argStrType.substr(0, 1);
		strText				= ' ' + strText.toUpperCase();
		strText				+= argStrType.substr(1);
		objSpan.appendChild(document.createTextNode(strText));
		
		var objDiv			= document.createElement('div');
		objDiv.className	= 'filter';
		objDiv.appendChild(objCheckbox);
		objDiv.appendChild(objSpan);
		
		// needs to be set after appendChild
		if ('blog' === argStrType) objCheckbox.checked = true;
		
		document.getElementById('filters').appendChild(objDiv);
	}
	
	/**
	 *	onFilterClick
	 *	
	 *	@access		private
	 *	@param		object		argObjClickEvent
	 *	@param		object		argObjCheckbox
	 *	@param		string		argStrType
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onFilterClick = function(argObjClickEvent, argObjCheckbox, argStrType)
	{
		// IE doesn't send a ClickEvent argument, so rearrange arguments
		if (undefined === argStrType)
		{
			argStrType		= argObjCheckbox;
			argObjCheckbox	= argObjClickEvent;
		}
		
		var intMarkerCnt = this.arrMarkers.length;
		for (var i = 0; i < intMarkerCnt; i++)
		{
			var objMarker = this.arrMarkers[i];
			if (argStrType === objMarker.strType)
			{
				var blnShow = argObjCheckbox.checked;
				if (true === objMarker.blnRecent) blnShow = this.blnShowRecent;
				
				(true === blnShow) ? objMarker.show() : objMarker.hide();
			}
		}
	}
	
	/**
	 *	onRecentFilterClick
	 *	
	 *	@access		private
	 *	@param		object		argObjCheckbox
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onRecentFilterClick = function(argObjCheckbox)
	{
		this.blnShowRecent = argObjCheckbox.checked;
		
		var intMarkerCnt = this.arrMarkers.length;
		for (var i = 0; i < intMarkerCnt; i++)
		{
			var objMarker = this.arrMarkers[i];
			if (true === objMarker.blnRecent)
			{
				(true === this.blnShowRecent) ? objMarker.show() : objMarker.hide();
			}
		}
	}
	
	/**
	 *	loadRss
	 *	
	 *	@access		private
	 *	@param		void
	 *	@return		void
	**/
	rnw.expat.Application.prototype.loadRss = function()
	{
		var objAjax = undefined;
		if (undefined !== window.XMLHttpRequest)
		{
			objAjax = new XMLHttpRequest();
		}
		else if (undefined !== window.ActiveXObject)
		{
			objAjax = new ActiveXObject('Microsoft.XMLHTTP');
		}
		else
		{
			return;
		}
		
		objAjax.onreadystatechange = Delegate.create(this, function()
		{
			if (4 === objAjax.readyState)
			{
				//if (null !== objAjax.responseXML) this.onRssLoad(objAjax.responseXML.documentElement);
				if (null !== objAjax.responseText) this.onLinksLoad(objAjax.responseText);
			}
		});
		
		objAjax.open('GET', this.strRssUrl, true);
		objAjax.send(null)
	}
	
	/**
	 *	onRssLoad
	 *	
	 *	@access		private
	 *	@param		xml		argObjXml
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onRssLoad = function(argObjXml)
	{
		var objLinks	= new Object();
		var arrEntries	= argObjXml.getElementsByTagName('entry');
		var intEntryCnt = arrEntries.length;
		for (var i = 0; i < intEntryCnt; i++)
		{
			var objEntry		= arrEntries[i];
			var strLink			= this.stripLink(objEntry.getElementsByTagName('link').item(0).attributes.getNamedItem('href').value);
			objLinks[strLink]	= true;
		}
		
		var intMarkerCnt = this.arrMarkers.length;
		for (var i = 0; i < intMarkerCnt; i++)
		{
			var objMarker		= this.arrMarkers[i];
			var strLink			= this.stripLink(objMarker.strLink);
			
			if (undefined !== objLinks[strLink])
			{
				objMarker.blnRecent				= true;
				objMarker.getIcon().imageOut	= './images/markers/new.png';
				objMarker.getIcon().imageOver	= './images/markers/new.png';
				
				objMarker.setImage(objMarker.getIcon().imageOut);
				
				objMarker.show();
			}
		}
	}
	
	/**
	 *	onRssLoad
	 *	
	 *	@access		private
	 *	@param		xml		argObjXml
	 *	@return		void
	**/
	rnw.expat.Application.prototype.onLinksLoad = function(argStrLinks)
	{
		var objLinks = new Object();
		
		var arrLinks = argStrLinks.split('\n');
		var intLinkCnt = arrLinks.length;
		for (var i = 0; i < intLinkCnt; i++)
		{
			objLinks[arrLinks[i]] = true;
		}
		
		var intMarkerCnt = this.arrMarkers.length;
		for (var i = 0; i < intMarkerCnt; i++)
		{
			var objMarker		= this.arrMarkers[i];
			var strLink			= this.stripLink(objMarker.strLink);
			
			if (undefined !== objLinks[strLink])
			{
				objMarker.blnRecent				= true;
				objMarker.getIcon().imageOut	= './images/markers/new.png';
				objMarker.getIcon().imageOver	= './images/markers/new.png';
				
				objMarker.setImage(objMarker.getIcon().imageOut);
				
				objMarker.show();
			}
		}
	}
	
	/**
	 *	stripLink
	 *	
	 *	@access		private
	 *	@param		string		argStrLink
	 *	@return		string
	**/
	rnw.expat.Application.prototype.stripLink = function(argStrLink)
	{
		argStrLink = argStrLink.split('\n').join('');
		argStrLink = argStrLink.split(' ').join('');
		
		if (0 === argStrLink.indexOf('<ahref="')) argStrLink = argStrLink.substr(8);
		if (0 === argStrLink.indexOf('http://')) argStrLink = argStrLink.substr(7);
		var intPos = argStrLink.indexOf('"');
		if (-1 !== intPos) argStrLink = argStrLink.substr(0, intPos);
		var intPos = argStrLink.indexOf('/');
		if (-1 !== intPos) argStrLink = argStrLink.substr(0, intPos);
		
		//var intPos = argStrLink.lastIndexOf('/');
		//if (intPos === argStrLink.length - 1) argStrLink = argStrLink.substr(0, intPos);
		
		argStrLink = 'http://' + argStrLink;
		
		return argStrLink;
	}
	
	/**
	 *	setCenter
	 *	
	 *	@access		public
	 *	@param		GLatLng		argObjLatLn
	 *	@param		integer		argIntZoomLevel
	 *	@return		boolean
	**/
	rnw.expat.Application.prototype.setCenter = function(argObjLatLn, argIntZoomLevel)
	{
		this.objMap.setCenter(argObjLatLn, argIntZoomLevel);
		this.objLargeMapControl.setZoom(argIntZoomLevel);
		
		return false;
	}