
/**
 * MarkerWrapper contains a maker and the layer that it belongs to. MarkerWrapper 
 * constructor additionally adds the wrapper as a parameter of the marker. 
 * Additional function that operate on marker wrapper pairs are static.
 * also no event are propagated from MarkerWrappers however changes are executed
 * from the layer that the wrapper belongs to.
 */
function MarkerWrapper(marker, layer)
{
	this.options=null;
	this.marker=marker;
	this.layer=layer;
	this.marker.wrapper=this;
}

MarkerWrapper.prototype={}; //extends object

/**
 * Marker Wrapper static methods
 * To keep markers lightweight all methods on markers are static methods.
 */ 

MarkerWrapper.getLayerManager=function(wrapper)
{
	return Layer.getLayerManager(wrapper.layer);
};

MarkerWrapper.getMediaMap=function(wrapper)
{
	return MarkerWrapper.getLayerManager(wrapper).mediaMap;
};

MarkerWrapper.getMap=function(wrapper)
{
	return MarkerWrapper.getMediaMap(wrapper).mainMap;
};

MarkerWrapper.getMarkerManager=function(wrapper)
{
	return MarkerWrapper.getMediaMap(wrapper).markerManager;
};

/**
 * initializes markers to respond to drag events. used by edit and reset methods.
 */
MarkerWrapper.setMarkerListener=function(wrapper)
{
	GEvent.addListener(wrapper.marker, 'dragend', function(l){
		if(!wrapper.change)
			MarkerWrapper.edit(wrapper,{latLng:l});
		(new EditInfoContent()).openMCEInfoWindow(wrapper);
		MarkerWrapper.getMediaMap(wrapper).menuOrderer.fadeIn();

	});
	GEvent.addListener(wrapper.marker, 'dragstart', function(l){
		MarkerWrapper.getMediaMap(wrapper).menuOrderer.fadeOut();
		wrapper.marker.closeInfoWindow();
	});
};

/**
 * saves the original marker if there are changes 
 * and updates the marker. some changes require a new marker to be made. 
 * so the updated marker is returned and may be a new marker. the wrapper
 * remains consistent. all reference to markers should be done by the wrapper to prevent 
 * losing reference to the current (most up to date) marker
 */
MarkerWrapper.edit=function(wrapper, options){
	var display=wrapper.marker||wrapper.shape;	//abstract working marker since it may change

	/*
	 * if not previously backed up then create backup and attach to wrapper
	 */

	if(!(wrapper.change&&wrapper.change=="new")&&!wrapper.original)//creates originalMarker if it doesn't (exist and (data is new or changed))
	{
		if(wrapper instanceof MarkerWrapper)
		{										//latLng could already be changed
			wrapper.original=new GMarker(wrapper.latLng,{'icon':display.getIcon(),title:display.getTitle()});
			wrapper.original.style=display.style;
		}
		else if(wrapper instanceof ShapeWrapper)
		{
			wrapper.original={};
			wrapper.original.title=display.title;
		}
		wrapper.original.description=display.description;
		wrapper.original.media=display.media; //not used
	}

	/*
	 * can't change icon or title!, must make a new marker
	 * first check to see if these fields have changed.
	 */
	if(wrapper instanceof MarkerWrapper)
		if(($defined(options.icon)&&!(display.getIcon().image===options.icon.image))||($defined(options.title)&&options.title!=''&&!(display.getTitle()===options.title)))
		{
			if(options.title=='')
				options.title=display.getTitle(); //force marker to have a title
			var tmpMarker=new GMarker(display.getLatLng(),
					{draggable:true,
				'icon':$pick(options.icon,display.getIcon()),
				'title':$pick(options.title,display.getTitle())});
			tmpMarker.description=display.description;
			tmpMarker.media=display.media;
			tmpMarker.style=display.style;
			tmpMarker.layer=display.layer;

			MarkerWrapper.getMarkerManager(wrapper).addMarker(tmpMarker,0);	//add created marker
			MarkerWrapper.getMarkerManager(wrapper).removeMarker(display);	//remove obsolete marker
			display=tmpMarker; //update display so remaining changes are applied to correct marker
			wrapper.marker=display;	//update wrappers reference
			display.wrapper=wrapper; //new marker also has the wrapper

			/*
			 * marker must save it's coordinates on drag. the following initializes the marker
			 */
			MarkerWrapper.setMarkerListener(wrapper); //call setup method to set markers drag events
			var rebuild=true;	//flag for later indicates that marker has been destroyed and recreated
		}

	/*
	 * the following have simple methods to change values, therefore do not require a new marker
	 */
	if(wrapper instanceof MarkerWrapper)
		if($defined(options.latlng))
			display.setLatLng(options.latlng);
	if($defined(options.description))
		display.description=options.description;
	if($defined(options.media))
		display.media=options.media;
	/*
	 * check to see difference between this and original marker. if no difference then 
	 * marker changes have not occurred or the user reverted them manually.
	 * if so, clear all evidence of changes
	 */
	if(wrapper instanceof MarkerWrapper){
		if(wrapper.original&&display.getTitle()==wrapper.original.getTitle()
				&&display.description==wrapper.original.description&&display.getLatLng()==wrapper.latLng&&display.media==wrapper.original.media&&display.getIcon().image==wrapper.original.getIcon().image)
		{ 
			/*no changes actually occurred or it was changed back by user!*/
			wrapper.original=null;
			if(wrapper.change=="edit"){
				wrapper.change=null;
				wrapper.layer.removeItemChange(wrapper); //keeps track of how many changes exists for the layer 
			}
		}
		else
		{
			wrapper.layer.addItemChange(wrapper); //causes the layer to fire its update event. 
		}
	}
	else if(wrapper instanceof ShapeWrapper)
	{
		if(wrapper.original&&display.title==wrapper.original.title&&display.description==wrapper.original.description&&ShapeWrapper.CompareCoords(display,wrapper.latlngs))
		{
			/*no changes actually occurred or it was changed back by user!*/
			wrapper.original=null;
			if(wrapper.change=="edit")
			{
				wrapper.change=null;
				wrapper.layer.removeItemChange(wrapper); //keeps track of how many changes exists for the layer 
			}
		}
	}
	/*if changed but no flag set on wrapper then attach new flag*/
	if(wrapper.original&&!wrapper.change)
	{
		wrapper.change="edit";	//NOTE: three states null 'edit' or 'new'
		wrapper.layer.addItemChange(wrapper);//update layer changes
	}

	/*
	 * optional function (from caller) onRebuild is called if the marker was remade (flag - rebuild)
	 */
	if(options.onRebuild&&rebuild)
		options.onRebuild();
};

MarkerWrapper.reset=function(wrapper,onRebuild)
{
	var orig=wrapper.original;
	if(orig)
	{
		if(!onRebuild)
		{
			onRebuild=function(){};
		}
		var options={
				latlng:orig.getLatLng(),
				description:orig.description,
				'onRebuild':onRebuild};

		if(wrapper instanceof MarkerWrapper)
		{
			options.icon=orig.getIcon();
			options.latlng=orig.getLatLng();
			options.title=orig.getTitle();

		}
		else if(wrapper instanceof ShapeWrapper)
		{
			options.latlngs=wrapper.latlngs;
			options.name=orig.title;
		}
		MarkerWrapper.edit(wrapper, options);
	}
};

/**
 * save commits changes to a marker to the server where it is expected to be updated in the kml file.
 */
MarkerWrapper.save=function(item ,options)
{	
	//TODO: - Depreciated save. remove any calls to this method from all other class etc:
	mm_debug("Depreciated MarkerWrapper.save!");
	MapFactory.SaveItem(item, options);
};

/**
 * similar to save except the marker will be removed from the kml file by Joomla
 */
MarkerWrapper.destroy=function(wrapper,options){
	//TODO: - Depreciated delete. remove any calls to this method from all other class etc:
	mm_debug("Depreciated MarkerWrapper.destroy!");
	MapFactory.DeleteItem(wrapper, options);

};

function ShapeWrapper(shape, layer)
{
	this.options=null;
	this.shape=shape;
	this.layer=layer;
	this.type="polygon";
	this.shape.wrapper=this;
}
ShapeWrapper.prototype={};














