/*
 * component-name: 		map - Carte interactive du mont Royal
 * component-version: 	2.0
 * component-author:	Jean-Georges Guénard (guenard@gmail.com)
	 
	- bug: Sur IE8, les slideshows n'affichent pas les images lorsqu'on revient en arrière
	- bug: Sur Firefox et IE8 lorsqu'on minimise la fenêtre il y a une bordure blanche a droite et en bas
*/
var map = {
		
	// Arbre DOM
	dom : {},
	
	// Données
	data : {},
	
	// Mesures
	x:0,	y:0,	vw:0,	vh:0,
	
	// Paramêtres
	settings: {},
	
	// Locales
	locales: {},
	
	// Effets
	effects: {},
	
	// Classes de popup
	popupClasses: {},
	
	// Intialisation de la carte
	init: function(step){
		var initSteps = {LOAD_STDVIEW:1,LOAD_LRGVIEW:2,LOAD_XML:3,LOAD_PLUGINS:4};
		// Chargement du modèle de données
		switch(step)
		{
			case initSteps.LOAD_STDVIEW:
				map.data.views = {};
				map.data.views.standard = $(new Image());
				map.data.views.standard.
					attr("id","viewport-rendered-image").
					load(function(){map.init(initSteps.LOAD_LRGVIEW);}).
					error(function(){map.report(map.locales["error-standard-view-notfound"]);}).
					attr("src",map.settings["standard-image"]);
				break;
			case initSteps.LOAD_LRGVIEW:
				map.data.views.large = $(new Image());
				map.data.views.large.
					attr("id","viewport-rendered-image").
					load(function(){map.init(initSteps.LOAD_XML);}).
					error(function(){map.report(map.locales["error-large-view-notfound"]);}).
					attr("src",map.settings["large-image"]);
				break;
			case initSteps.LOAD_XML:
				$.ajax({
					type:"GET",
					url:map.settings["data-url"],
					dataType: ($.browser.msie) ? "text" : "xml",
					success:function(response){
						if($.browser.msie){
							map.data.xml = new ActiveXObject("Microsoft.XMLDOM");
							map.data.xml.async = false;
							map.data.xml.loadXML(response);
							map.data.xml = $(map.data.xml);
						} else {
							map.data.xml = $(response);
						}
						map.data.filters = $(map.data.xml.find("filters")[0]).find("filter");
						map.data.locations = $(map.data.xml.find('locations')[0]).find("location");
						map.init(initSteps.LOAD_PLUGINS);
					},
					error:function(req,txt,err){
						map.report(map.locales["error-invalid-xml"]+" ["+txt+req+"]");
					}
				});				
				break;
			case initSteps.LOAD_PLUGINS:
				if(hs)
				{
					hs.graphicsDir = map.settings["highslide-graphics"];
					hs.outlineType = 'outer-glow';
					hs.showCredits = false;
					hs.preserveContent = true;
					hs.allowSizeReduction = false;
				}
				map.render();
				break;
			default:
				map.x = map.y = 0;
				map.data.views = {};
				// Chargement du DOM en mémoire
				map.dom.loading = $('#loading-layer');
				map.dom.loadingMessage = $('#loading-message');
				map.dom.ui = $('#ui-layer');
				map.dom.themeFilters = $('#menu-theme-filters');
				map.dom.menu = $('#menu');
				map.dom.viewport = $('#viewport');
				map.dom.renderingSurface = $('#viewport-rendering-surface');
				map.dom.viewportControls = {
					scrollUp : $('#viewport-control-scrollUp'),
					scrollDown : $('#viewport-control-scrollDown'),
					scrollRight : $('#viewport-control-scrollRight'),
					scrollLeft : $('#viewport-control-scrollLeft'),
					showLegend : $('#viewport-control-showLegend')
				};
				map.dom.menuControls = {
					zoomIn : $('#menu-zoom-in'),
					zoomOut : $('#menu-zoom-out')
				};
				map.dom.templates = {
					menuFilter : $('#menu-filter-template'),
					marker : $('#marker-template')
				};
				map.dom.popups = {};
				// Bindings
				map.dom.viewportControls.scrollUp.bind('mousedown',function(event){map.scroll(0,1);}).bind('mouseup',map.stopScroll).bind('mouseout',map.stopScroll);
				map.dom.viewportControls.scrollDown.bind('mousedown',function(event){map.scroll(0,-1);}).bind('mouseup',map.stopScroll).bind('mouseout',map.stopScroll);
				map.dom.viewportControls.scrollLeft.bind('mousedown',function(event){map.scroll(1,0);}).bind('mouseup',map.stopScroll).bind('mouseout',map.stopScroll);
				map.dom.viewportControls.scrollRight.bind('mousedown',function(event){map.scroll(-1,0);}).bind('mouseup',map.stopScroll).bind('mouseout',map.stopScroll);
				map.dom.menuControls.zoomIn.bind('click',function(event){map.zoom(map.data.views.large);});
				map.dom.menuControls.zoomOut.bind('click',function(event){map.zoom(map.data.views.standard);});
				map.dom.loading.css("display","block");
				// Chargement des plugins
				for (var popupClassName in map.popupClasses)
					map.popupClasses[popupClassName].init();
				// Chargement des données
				map.init(initSteps.LOAD_STDVIEW);
				break;
		}
	},
	
	// Installation d'un plugin
	addPopupClass: function(name,instance){
		map.popupClasses[name] = instance; 
	},
	
	// Fonction de rendu de la carte
	render: function(){
		// Chargement des filtres
		if(map.data.filters.length>0)
		{
			$("#menu-no-filters").remove();
			map.data.filters.each(function(){
				var filterEntry = $(this);
				var filterElement = map.dom.templates.menuFilter.clone();
				$(filterElement.find('.menu-filter-control')[0]).attr('id','filter-theme'+filterEntry.attr('id'));
				$(filterElement.find('.menu-filter-label')[0]).text(filterEntry.attr('caption'));
				map.dom.themeFilters.append(filterElement);						
			});
		}
		// Chargement des marqueurs
		map.data.locations.each(function(){
			var locationEntry = $(this);
			var locationThemes = locationEntry.find('filter');		
			var locationPopupTriggerID = "popupTrigger"+locationEntry.attr('id');
			var locationMarker = map.dom.templates.marker.clone().attr('id',"marker"+locationEntry.attr('id'));
			if(map.popupClasses[locationEntry.attr('class')])
			{
				// Ajout des filtres
				locationMarker.addClass("class"+locationEntry.attr('class'));
				locationThemes.each(function(){locationMarker.addClass("theme"+$(this).attr('id'));});
				// Positionnement
				locationMarker.css('top',locationEntry.attr('y')+'px').css('left',locationEntry.attr('x')+'px');			
				$(locationMarker.find('.marker-icon')[0]).attr('src','theme/graphics/markers/'+map.popupClasses[locationEntry.attr('class')].markerIcon);
				map.dom.renderingSurface.append(locationMarker);
				// Liaison du marqueur avec les autres plugins
				$(locationMarker.find('.marker-trigger')[0]).attr('title',locationEntry.attr('caption')).tooltip({showURL: false,delay:0});
				$(locationMarker.find('.marker-trigger')[0]).attr('id',locationPopupTriggerID).bind('click',function(){return map.showPopup(this);});
			}
		});	
		// Activation des contrôles de filtrage
		$('.menu-filter-control').each(function(){$(this).bind('click',function(){map.filter($(this));});});
		// Etat : Chargement terminé
		map.dom.loading.css("display","none");
		map.dom.ui.css("display","block");
		map.resize();
		map.zoom(map.data.views.standard);
		return hs.htmlExpand(document.getElementById('popup-welcome-trigger'),{objectType:'inline',contentId:'popup-welcome', align:'center'});
	},
	
	// Retourne un pointeur vers les informations d'un POI
	getLocation: function(locationID){
		var result = null;
		map.data.locations.each(function(){
			var locationEntry = $(this);
			if(locationEntry.attr('id') == locationID)
				result = locationEntry;
		});
		return result;
	},
		
	// Affichage d'un popup
	showPopup: function(trigger){
		var locationID = $(trigger).attr('id').replace('popupTrigger','');
		var popupID = "popup"+locationID;
		if(!map.dom.popups[popupID])
		{
			// Génération du popup lors du premier loading
			var locationEntry = map.getLocation(locationID);
			map.dom.popups[popupID] = map.popupClasses[locationEntry.attr('class')].render(popupID,locationEntry);
			map.dom.renderingSurface.append(map.dom.popups[popupID]);
			if(map.popupClasses[locationEntry.attr('class')].postRender)
				map.popupClasses[locationEntry.attr('class')].postRender(map.dom.popups[popupID],locationEntry);
		}
		// Affichage du popup
		return hs.htmlExpand(trigger,{objectType:'inline', contentId:popupID});
	},
	
	// Application d'un filtre aux marqueurs
	filter: function(trigger){
		var filterName = trigger.attr('id').replace('filter-','');
		var checked = trigger.attr('checked');
		$('.'+filterName).each(function(){
			$(this).css('visibility',(checked)?'visible':'hidden');
		});
	},
	
	// Affichage de message d'erreur
	report: function(message){
		map.dom.loadingMessage.html(map.locales["error"]+message);
	},
	
	// Zoom sur la carte
	zoom: function(view){
		// Remplacement de l'image
		var lw=0,nw=0,nh=0;
		if(map.dom.view){
			lw = map.dom.renderingSurface.width();
			map.dom.view.remove();
		}
		map.dom.renderingSurface.append(view);
		nw=map.dom.renderingSurface.width();
		nh=map.dom.renderingSurface.height();
		map.scrollTo(-((nw-map.vw)/2),-((nh-map.vh)/2));
		map.dom.view = $("#viewport-rendered-image");
		// Ajustement de la position des marqueurs
		if(lw>nw)
		{
			// Position initiale
			map.data.locations.each(function(){
				var locationEntry = $(this);
				var markerElement = $('#marker'+locationEntry.attr('id'));
				markerElement.css("top",locationEntry.attr('y')+"px");
				markerElement.css("left",locationEntry.attr('x')+"px");
			});
		} else if (lw>0&&lw<nw) {
			// Agrandissement
			map.data.locations.each(function(){
				var locationEntry = $(this);
				var markerElement = $('#marker'+locationEntry.attr('id'));
				markerElement.css("left",(locationEntry.attr('x')*map.settings["zoom-ratio"])+"px");
				markerElement.css("top",(locationEntry.attr('y')*map.settings["zoom-ratio"])+"px");
			});
		}
	},
	
	// Ajustement des composantes selon la taille du navigateur
	resize:	function(){
		map.ww = $(window).width();
		map.wh = $(window).height();
		var mw = parseInt(map.dom.menu.css('width'));
		map.vh = (map.wh>map.settings["min-height"])?map.wh:map.settings["min-height"];
		map.vw = (map.ww>map.settings["min-width"])?map.ww-mw:map.settings["min-width"]-mw;
		var cl = ((map.vw-map.settings["viewport-controls-size"])/2);
		var ct = ((map.vh-map.settings["viewport-controls-size"])/2);
		map.dom.menu.css("height",map.vh+"px");
		map.dom.viewport.css("height",map.vh+"px").css("width",map.vw+"px");
		map.dom.viewportControls.scrollUp.css("top",map.settings["viewport-controls-margin"]+"px").css("left",cl+"px");
		map.dom.viewportControls.scrollDown.css("bottom",map.settings["viewport-controls-margin"]+"px").css("left",cl+"px");
		map.dom.viewportControls.scrollLeft.css("left",map.settings["viewport-controls-margin"]+"px").css("top",ct+"px");
		map.dom.viewportControls.scrollRight.css("right",map.settings["viewport-controls-margin"]+"px").css("top",ct+"px");
		map.dom.viewportControls.showLegend.css("left",map.settings["viewport-controls-margin"]+"px").css("bottom",map.settings["viewport-controls-margin"]+"px");
		if(hs){
			hs.Expander.prototype.onDrag = function (sender, e) {
				var x = (e.left+e.dX);
				var y = (e.top+e.dY);
				if(x<0||y<0||x>(map.ww-(e.width+10))||y>(map.wh-(e.height+10))) return false;
			}
		}
	},
	
	// Effet de scrolling
	scrollTo: function(x,y){
		map.x = x, map.y = y;
		map.dom.renderingSurface.css("left",map.x+"px").css("top",map.y+"px");
	},
	scroll: function(dX,dY){
		var nx = map.x+(dX*map.settings['scrolling-increment']);
		var ny = map.y+(dY*map.settings['scrolling-increment']);
		if(	nx < map.settings["scrolling-margin"] && 
			ny < map.settings["scrolling-margin"] && 
			nx > -((map.dom.view.attr('width') + map.settings["scrolling-margin"])-map.vw) &&
			ny > -((map.dom.view.attr('height') + map.settings["scrolling-margin"])-map.vh))
		{
			map.scrollTo(nx,ny);		
			map.effects.scrolling = setTimeout("map.scroll("+dX+","+dY+");",map.settings['scroll-speed']);	
		}
	},
	stopScroll: function(){
		if(map.effects.scrolling){
			clearTimeout(map.effects.scrolling);
			map.effects.scrolling = null;
		}
	}
}

$(document).ready(map.init);
$(window).bind('resize', map.resize);
