/**
 * File - GeoliveLayer.js
 * Package - Geolive. http://www.geolive.ca
 * Updated - Jan 25 10
 * Author - Nick Blackwell UBCO, Jon Corbett Phd, Michael Udala UBCO, Shane Wright UBCO.
 * 
 * License - Creative Commons Attribution-Share Alike 2.5 Generic http://creativecommons.org/licenses/by-sa/2.5/
 *
 * Description - Defines Geolive's Layer Class which is a container for MapItems, MapItem.js
 * provides wrappers for all Google Map Items. (note: only Network Links so far.)
 * Layers can be loaded using google's GGeoXml Method, which will cause the layer to be 
 * controlled externally (no custome infowindows, no entries for individual items) or
 * parsed by SimpleParser.js
 * 
 * Dependencies - GoogleMaps API, Mootools 1.11, SimpleParser.js, MapFactory.js
 */



var Layer=new Class({
	/* default options */
	options:
	{
	icon:null,
	style:null,	//style contains an icon url overriding icon
	name: null,
	description:null,
	id:-1,	
	loadWhen:"later",				
	loadHow:"geoload",				
	url:null,						
	writeAccess:"registered",		
	readAccess:"public",
	legend:null
	},
	initialize:function(parent, options)
	{
		//mm_debug(options);
		var me=this;
		me.addEvent('onLoad',function(){
			me.isLoaded=true;
		});
		me.isLoaded=false;
		/*depreciated variable conflicts with mootools Class*///me.parent=parent; ///aaahhh extending this class will f this up...
		me.parentLayer=parent;
		me.setOptions(options);
		me.change=0;		/*to keep track of the number of objects that are currently*/
		if(this.options.loadWhen=="now")
		{
			me.load();
			me.isHidden=false;
			me.isLoaded=true;
		}
	},
	addItem:function(item, itemList){
		var me=this;
		itemList.push(item);
		if(item.change)	me.addItemChange(item);
		else me.fireEvent("onUpdate");
		me.fireEvent("onAddItem",item);
	},
	addItemChange:function(item){
		var me=this;
		me.change++;
		me.fireEvent('onItemChange', [me.change, item]);
		me.fireEvent("onUpdate");
	},
	removeItemChange:function(item){
		var me=this;
		me.change--;
		me.fireEvent('onItemChange', [me.change, item]);
		me.fireEvent("onUpdate");
	},
	addMarker:function(marker){if(!this.markers){this.markers=[];}this.addItem(marker,this.markers);
	MapFactory.SetMarkerClickEvents(marker);
	MapFactory.SetMarkerDragEvents(marker);
	
	
	},
	addShape:function(polygon){if(!this.polygons){this.polygons=[];}this.addItem(polygon,this.polygons);},
	addSublayer:function(layer){if(!this.extOverlays){this.extOverlays=[];}this.addItem(layer,this.extOverlays);}, 

	removeItem:function(item, itemList){
		var me=this;
		var tmp=[];
		var i;
		while(itemList.length>0){
			i=itemList.pop();
			if(i!=item)
			{
				tmp.push(i);
			}
		}
		while(tmp.length>0){
			i=tmp.pop();
			itemList.push(i);
		}		
		if(item.change)	me.removeItemChange(item);
		else me.fireEvent("onUpdate");
		me.fireEvent("onRemoveItem",item);
	},
	removeMarker:function(marker){this.removeItem(marker, this.markers);},
	removePolygon:function(polygon){this.removeItem(polygon, this.polygons);},
	removeSublayer:function(layer){this.removeItem(layer, this.extOverlays);},
	hide:function(){
		$each(this.markers,function(marker){ MapFactory.AbstractItem(marker).hide();}); //TODO Transistional. should all define show()
		$each(this.polygons,function(polygon){ MapFactory.AbstractItem(polygon).hide();});
		$each(this.networkLinks,function(networkLink){networkLink.hide();});
		$each(this.overlays,function(overlay){overlay.setMap(null);});
		this.isHidden=true;
		this.fireEvent("onHide");
	},
	redraw:function(){
		var me=this;
		$each(me.polygons,function(wrapper){
			if(me.isLoaded)
			{
				MapFactory.GetGMap(me).addOverlay(wrapper.shape);
				wrapper.shape.show();
				wrapper.shape.redraw(true);
				
			}
		});
	},
	show:function(){
		var me=this;
		if(!me.isLoaded)
			me.load(me);
		else{
			$each(this.markers,function(marker){ MapFactory.AbstractItem(marker).show();}); //TODO Transistional. should all define show()
			$each(this.polygons,function(polygon){ MapFactory.AbstractItem(polygon).show();});
			$each(this.networkLinks,function(networkLink){networkLink.show();});
			$each(this.overlays,function(overlay){overlay.setMap(MapFactory.GetGMap(me));});
			this.isHidden=false;
			this.fireEvent("onShow");
		}
	},
	load:function(){	
		var me=this;
		if(me.isUnloaded){
			me.reload();
		}else{
			if(me.options.loadHow!="geoload")
			{
				var layerQuery=new LayersRequest(me,"kml");
				layerQuery.addEvent('onSuccess',function(xml){
					
				
					var parser=new SimpleParser(Layer.GenerateTransformFunctions(me));	
					mm_debug(["Geolive Layer. Parsing KML - "+me.options.name,{me:me, parser:parser}]);
					me.loadDocument(xml);			
					
					parser.parseMarkers(xml); //appends markers automatically to this instance

					me.polygons=parser.parsePolygons(xml);
					me.polygons=me.polygons.concat(parser.parseLines(xml)); //lines are treated the same as polygons. 
					me.networkLinks=parser.parseNetworklinks(xml);
					me.isLoaded=true;
					me.fireEvent('onLoad');
					me.fireEvent('onUpdate');
					me.fireEvent('onShow');

				});
				layerQuery.execute();
			}
			else{	/*expect me.options.loadHow=="parse"*/

				/**
				 * TODO: geoloading layers can cause unpredictable behaviour. google caches pages by name, changing layers 
				 * without changing the name, is not enough to update layer, often, the layer must be renamed. 
				 * or... nice hack add a url variable to the end ie: http://file.kml?trickGoogle=hellYesss
				 */
				var overlay=new google.maps.KmlLayer(MapFactory.GetMM(me).options.site+"components/com_mediamapserver/kmlDocs"+me.options.path+"?r="+Math.round(Math.random()*100),{
							preserveViewport:true, 
							suppressInfoWindows:(me.options.showPopups&&me.options.showPopups=="hide"?true:false)
						}); 
				google.maps.event.addListener(overlay, 'click',function(kmlEventObject){
					mm_debug(["KMLayer Click Event", {layer:me}]);
					MapFactory.GetMM(me).eventManager.fireEvent('onOverlayClick', [me, kmlEventObject]);
				});
				//while(!overlay.hasLoaded){}
				//MapFactory.GetGMap(me).addOverlay(overlay);
				//overlay.show();
				overlay.setMap(MapFactory.GetGMap(me));
				me.overlays=[];
				me.overlays.push(overlay);
				me.fireEvent('onLoad');
				me.fireEvent('onUpdate');
				me.fireEvent('onShow');
			}

		}
	},
	/**
	 * private method
	 */

	unload:function(discard){
		var me=this;
		if(!me.isLoaded)
			Layer.load(me);

		$each(this.markers,function(wrapper){MapFactory.GetMM(me).markerManager.removeMarker(wrapper.marker);});
		$each(this.polygons,function(wrapper){MapFactory.GetGMap(me).removeOverlay(wrapper.shape);});
		$each(this.networkLinks,function(networkLink){MapFactory.GetGMap(me).removeOverlay(networkLink.getOverlay());});
		$each(this.overlays,function(overlay){MapFactory.GetGMap(me).removeOverlay(overlay);});

		this.fireEvent("onUnload");
		this.fireEvent("onUpdate");
		if(discard){
			me.polygons=null;
			me.networkLinks=null;
			me.markers=null;
			me.overlays=null;
		}else
		{
			me.isUnloaded=true;
		}
		me.isLoaded=false;
	},
	reload:function(){
		var me=this;
		//TODO: for sorting: want to apply layers from bottom to top, (in palet list) ie, me.markers.reverse();
		if(this.markers)
			$each(this.markers,function(wrapper){MapFactory.GetMM(me).markerManager.addMarker(wrapper.marker,0);});
		if(this.polygons)
			$each(this.polygons,function(wrapper){MapFactory.GetGMap(me).addOverlay(wrapper.shape);});
		if(this.networkLinks) {
			$each(this.networkLinks,function(networkLink) {
				//mm_debug(networkLink.getOverlay());
				MapFactory.GetGMap(me).addOverlay(networkLink.getOverlay());
			});
		}
		if(this.overlays)
			$each(this.overlays,function(overlay){MapFactory.GetGMap(me).addOverlay(overlay);});
		this.fireEvent("onReload");
		//this.fireEvent("onUpdate");

		me.isUnloaded=false;
		me.isLoaded=true;
	},


	loadDocument:function(xmlDom){
		var me=this;
		var documents=[];
		var parser=new SimpleParser();
		documents=parser.parseDocuments(xmlDom);

		if(documents.length>1){
			//TODO: multiple documents within dom. 
			//extract xml snippets and load as Folders.	
		}else /*TODO: check if there is no Document*/{
			var data=documents[0];
			if(!me.options.name||me.options.name=="") me.options.name=(data.name||"");
			if(!me.options.description||me.options.description=="") me.options.description=(data?(data.description||""):"");
		}	

	}
});




Layer.implement(new Events(), new Options());
Layer.GenerateTransformFunctions=function(instance){
	var me=instance;
	return {
		markerTransform:function(data)
		{
		var marker=MapFactory.CreateMarker(data,function(marker){
			//var markerContainer=new MarkerWrapper(marker,me);
			var markerContainer=new GeoliveMarker(marker,me);

			if(!me.markers)me.markers=[];
			me.markers.push(markerContainer);
			markerContainer.latLng=markerContainer.getLatLng();
			//MapFactory.GetMM(markerContainer).markerManager.addMarker(marker,0);
			markerContainer.show();
			MapFactory.SetMarkerDragEvents(markerContainer);
			MapFactory.SetMarkerClickEvents(markerContainer);
			$each(data.tags,function(v,k){
				t={};
				t[k]=v;
				MapFactory.SetTag(markerContainer, t);
			});
			me.fireEvent('createdMarker', markerContainer);
		});
		return null;
		},

		polygonTransform:function(polygonData, xml)
		{
			var polygon=MapFactory.CreatePolygon(polygonData.coordinates, polygonData);
			//var shapeContainer=new ShapeWrapper(polygon,me);
			var shapeContainer=new GeolivePolygon(polygon,me);

			//MapFactory.GetGMap(shapeContainer).addOverlay(polygon);
			shapeContainer.show();
			shapeContainer.type="polygon";		
			MapFactory.GetMM(shapeContainer).infoWindowViewer.initializePolygon(polygon);
			$each(polygonData.tags,function(v,k){
				t={};
				t[k]=v;
				MapFactory.SetTag(shapeContainer, t);
			});
			shapeContainer.name=polygonData.name;
			polygon.description=polygonData.description;
			shapeContainer.lineWidth=polygonData.lineWidth;
			shapeContainer.lineColor=SimpleParser.KMLConversions.RGBColorToKML(polygonData.lineColor,polygonData.lineOpacity);
			shapeContainer.polyColor=SimpleParser.KMLConversions.RGBColorToKML(polygonData.polyColor,polygonData.polyOpacity);
			shapeContainer.outline=polygonData.outline;
			return shapeContainer;
		},

		lineTransform:function(polygonData, xml)
		{
			var line=MapFactory.CreateLine(polygonData.coordinates, polygonData);
			//var shapeContainer=new ShapeWrapper(polygon,me);
			var shapeContainer=new GeoliveLine(line,me);

			//MapFactory.GetGMap(shapeContainer).addOverlay(line);
			shapeContainer.show();
			shapeContainer.type="line";
			MapFactory.GetMM(shapeContainer).infoWindowViewer.initializePolygon(line);
			$each(polygonData.tags,function(v,k){
				//mm_debug(v+"  "+k);
				t={};
				t[k]=v;
				MapFactory.SetTag(shapeContainer, t);
			});
			shapeContainer.name=polygonData.name;
			line.description=polygonData.description;
			shapeContainer.lineWidth=polygonData.lineWidth;
			shapeContainer.lineColor=SimpleParser.KMLConversions.RGBColorToKML(polygonData.lineColor,polygonData.lineOpacity);
			return shapeContainer;
		},

		networklinkTransform:function(data){
			item=GeoliveMapItem.CreateLink(data);
			//MapFactory.GetGMap(instance).addOverlay(item.getOverlay());
			item.show();
			MapFactory.GetGMap(instance).addOverlay(item.getOverlay());
			return item;
		}
	};
};


