/*********************************************************************
 * JS - Bibliothek H-Power 24h Stützpunktenetz                       *
 * ----------------------------------------------------------------- *
 * Javascript - Sammlung von Funktionen und Klassen zur Steuerung    *
 * der Applikation. Folgende externe APIs kommen innerhalb dieser    *
 * Bibliothek zur Verwendung und müssen im Kopfbereich des Haupt-    *
 * dokumentes deklariert sein:                                       *
 *                                                                   *
 * - Prototype Javascript Framework v1.6.0.2                         *
 *   http://www.prototypejs.org/download                             *
 *                                                                   *
 * - Google Maps API v2.x                                            *
 *   http://code.google.com/apis/maps/documentation/                 *
 *                                                                   *
 * - ExtInfoWindow (Customized Maps - InfoWindow)                    *
 *   http://gmaps-utility-library-dev.googlecode.com/svn/trunk/~     *
 *          extinfowindow/docs/examples.html                         *
 *                                                                   *
 * - DragZoomControl Class v1.2                                      *
 *   http://gmaps-samples.googlecode.com/svn/trunk/dragzoom/~        *
 *          dragzoom_professional.html                               *
 *                                                                   *
 * @author mku@h2g.ch                                                *
 * @version 1.0                                                      *
 *                                                                   *
 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE   *
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR      *
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;   *
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF     *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLU- *
 * DING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF*
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE  *
 *********************************************************************/ 

/**
 * Controlpanel Interface als Bindung zwischen der Map - Applikation
 * und dem Benutzerinterface (Standorteingabe, Registerkarten etc.).
 * Diese Klasse enthält vor allem Verweise und nützliche Steuerfunk-
 * tionen.
 */
var ControlPanel = Class.create({
	mapStateExtended: false,
	currentPoint: null,
	directionPanel: null,
	getMapState: function() {
		return (this.mapStateExtended) ? 'large' : 'small';
	},
	toggleMapState: function() {
		this.mapStateExtended = (this.mapStateExtended) ? false : true;
	},
	getScreenWidth: function() {
		return document.viewport.getWidth();
	},
	getScreenHeight: function() {
		return document.viewport.getHeight();
	},
	getDetailPane: function() {
		var pane = document.getElementById('pane-tab2');
		return (pane) ? pane : null;
	},
	showDetailPane: function() {
		showPane('tab2');
	},
	resetCurrentBasepoint: function() {
		if (this.currentPoint != null) {
			this.currentPoint.style.backgroundColor = '#FFFFFF';
			this.currentPoint = null;
		}
	},
	markBasepoint: function(id) {
		this.resetCurrentBasepoint();
		var box = document.getElementById('base_' + id);
		if (box) {
			box.style.backgroundColor = '#E4E4E4';
			this.currentPoint = box;
		}
	},
	isCurrentPoint: function(basepoint) {
		if (this.currentPoint != null) {
			return (basepoint.id == this.currentPoint.id);
		} else { return false; }
	},
	resetDirectionPanel: function() {
		if (this.directionPanel != null) {
			this.directionPanel.style.display = 'none';
			this.directionPanel = null;
		}
	},
	showDirectionPanel: function(panel) {
		this.resetDirectionPanel();
		this.directionPanel = panel;
		this.directionPanel.style.display = 'block';
	}
});
var cpanel = new ControlPanel();

/**
 * Observer - Funktionen: dienen zur Steuerung des Interfaces
 * wie Registerkarten umschalten, Karte vergrössern bzw. ver-
 * kleinern und Viewport Grösse anpassen je nach Fensterab-
 * messungen.
 */
function resizeViewport() {
	var margins = new Margins(140,0,0,0);
	$('main-canvas').maximizeHeight(margins);
	margins = (Prototype.Browser.IE) ?
		new Margins(0,0,10,0) : new Margins(0,0,0,0);
	$('map').maximizeHeight(margins);
	$('map').setStyle({ display: 'block' });
	var panes = document.getElementById('left-canvas');
	if (panes) {
		for (var i = 0; i < panes.childNodes.length; i++) {
			if (panes.childNodes[i].className == 'pane') {
				var margins = new Margins(0,0,130,0);
				$(panes.childNodes[i].id).maximizeHeight(margins);
			}
		}
	}
	handler.checkMapsize();
}
function registerObserver(flag) {
	if (flag) {
		Event.observe(window, 'resize', resizeViewport);
		$('toggle').observe('click', toggleMapState);
		var tabs = $('tabs').getElementsByTagName('a');
		for (var i = 0; i < tabs.length; i++) {
			$(tabs[i]).observe('click', switchPane);
		}
	}
}
function toggleMapState(event) {
	var element = Event.element(event);
	var toggle = document.getElementById('toggle');
	var map = document.getElementById('map');
	var canvas = document.getElementById('left-canvas');
	var togglePos = (cpanel.getMapState() == 'large') ? '345px' : '0px';
	var bgImage = (cpanel.getMapState() == 'large') ? 'small' : 'wide';
	var margin = (cpanel.getMapState() == 'large') ? '0 0 0 353px' : '0 0 0 7px';
	var display = (cpanel.getMapState() == 'large') ? 'block' : 'none';
	toggle.style.left = togglePos;
	toggle.style.backgroundImage = 'url(../img/icon_pane_' + bgImage + '.png)';
	map.style.margin = margin;
	canvas.style.display = display;
	cpanel.toggleMapState();
	handler.checkMapsize();
}
function switchPane(event) {
	var element = Event.element(event);
	showPane(element.name);	
}
function showPane(pane) {
	hideAllPanes();
	var tabs = $('tabs').getElementsByTagName('a');
	for (var i = 0; i < tabs.length; i++) {
		if (tabs[i].name == pane)
			$(tabs[i]).addClassName('active');
	}
	var pane = document.getElementById('pane-' + pane);
	if (pane) { pane.style.display = 'block'; }
}
function hideAllPanes() {
	var tabs = $('tabs').getElementsByTagName('a');
	for (var i = 0; i < tabs.length; i++) {
		$(tabs[i]).removeClassName('active');
		var pane = document.getElementById('pane-' + tabs[i].name);
		if (pane) { pane.style.display = 'none';	}
	}
}
var Margins = Class.create({
	top: 0,
	right: 0,
	bottom: 0,
	left: 0,
	initialize: function(top, right, bottom, left) {
		this.top = (Prototype.Browser.IE) ? (top - 3) : top;
		this.right = (Prototype.Browser.IE) ? (right - 3) : right;
		this.bottom = (Prototype.Browser.IE) ? (bottom - 3) : bottom;
		this.left = (Prototype.Browser.IE) ? (left - 3) : left;
	}
});
var Resizable = {
	maximizeCanvas: function(element, margins) {
		element = $(element);
		var parentWidth = $($(element).parentNode).getWidth();
		var parentHeight = $($(element).parentNode).getHeight();
	},
	maximizeHeight: function(element, margins) {
		element = $(element);
		var parentHeight = $($(element).parentNode).getHeight();
		element.style.height = (parentHeight - (margins.top + margins.bottom)) + 'px';
	},
	maximizeWidth: function(element, margins) {
		element = $(element);
		var parentWidth = $($(element).parentNode).getWidth();
		element.style.width = (parentWidth - (margins.left + margins.right)) + 'px';
	}
}
Element.addMethods(Resizable);

/**
 * Interface für die Steuerung der Map, unterteilt in einzelne Bereiche
 * wie Initialisierung, DomListeners, Standortsuche, DetailInfoPane mit
 * Stützpunkten aktualisieren, div. Hilfsfunktionen.
 */
function MapHandler(canvas) {
	this.canvas = canvas;
	this.map = null;
	this.geocoder = new GClientGeocoder();
	this.initialPoint = new GLatLng(47.4, 8.065);
	this.zoom = 10;
	this.radius = 10;
	this.currentLocation = null;
	this.currentDirections = null;
	this.currentMarker = null;
	this.extInfoWindow = null;
}
MapHandler.prototype.init = function() {
	var mainInstance = this;
	if (GBrowserIsCompatible()) {
		this.map = new GMap2(document.getElementById(this.canvas));
		// Adding Zoom Controls
		var boxStyleOpts = { opacity: .2, border: "2px solid #F79339" };
		var otherOpts = {
			buttonHTML: '<img src="img/zoom-control-inactive.png" />',
			buttonZoomingHTML: '<img src="img/zoom-control-active.png" />',
			buttonStartingStyle: { width: '17px', height: '17px' },
			overlayRemoveTime: 0
		};
		if (this.map) {
			with (this.map) {
				addControl(new GScaleControl());
				addControl(new DragZoomControl(boxStyleOpts, otherOpts, {}),
					new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(27,7)));
				addControl(new GLargeMapControl(),
					new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7,32)));
				setCenter(this.initialPoint, this.zoom);
				enableScrollWheelZoom();
			}
		}
		// Adding Listener for Infotab - Panes
		GEvent.addDomListener(this.map, 'extinfowindowupdate', function() {
			var tabs = $('infotab-tabs').getElementsByTagName('a');
			for (var i = 0; i < tabs.length; i++) {
				GEvent.addDomListener(tabs[i], 'click', function(e) {
					element = this;
					var _tabs = $('infotab-tabs').getElementsByTagName('a');
					for (var j = 0; j < _tabs.length; j++)
						$(_tabs[j]).removeClassName('active');
					$(element).addClassName('active');
					var currentPane = document.getElementById(element.id + '_content');
					if (currentPane) {
						var panes = $('infotab-content').getElementsByTagName('div');
						for (var s = 0; s < panes.length; s++) {
							if (panes[s].className == 'infopane') {
								$(panes[s]).addClassName('hide');
							}
						}
						$(currentPane).removeClassName('hide');
					}
					mainInstance.map.getExtInfoWindow().resize();
				});
			}
		});
	}
	this.browseLocations(this.initialPoint, true);
}
MapHandler.prototype.checkMapsize = function() { this.map.checkResize(); }
MapHandler.prototype.getRadius = function(initial) { return (initial) ? 1000 : this.radius; }
MapHandler.prototype.addMarker = function(id, point, customIcon) {
	var mainInstance = this;
	markerOptions = { icon:customIcon };
	var marker = new GMarker(point, markerOptions);
	GEvent.addListener(marker, 'click', function() {
		mainInstance.clearMarker(null);
		mainInstance.clearDirections();
		cpanel.markBasepoint(id);
		cpanel.resetDirectionPanel();
		marker.openExtInfoWindow(
			mainInstance.map,
			"base-infotab",
			'<div id="inner-infotab" style="width:400px;margin-bottom:' + ((Prototype.Browser.IE) ? '68px' : '65px') +
			';"><div class="tabs"><ul><li><a href="#" id="infotab1" class="active">' +
			'St&uuml;tzpunkt</a></li><li><a href="#" id="infotab2">Details</a></li></ul>' +
			'</div><div class="content"><div id="infotab1_content" class="loader"><img src="img/ajax-loader.gif"' +
			' width="32" height="32" alt="loading ..." title="loading ..."</div></div></div></div>',
			{
				ajaxUrl: "ajax/infotab_fr.php?id=" + id,
				beakOffset: 12
			}
		);
	});
	this.map.addOverlay(marker);
	return marker;
}
MapHandler.prototype.searchLocations = function(form) {
	var mainInstance = this;
	var address = form.location.value;
	this.radius = form.radius.value;
	this.geocoder.getLatLng(address, function(latlng) {
		if (!latlng) {
			mainInstance.currentLocation = null;
			var detailPane = cpanel.getDetailPane();
			var box = new Element('div', { 'class' : 'box-top' });
			box.update(
				'Pas de résultat pour cette adresse <b>' +
				form.location.value + '</b>'
			);
			detailPane.innerHTML = '';
			detailPane.appendChild(box);
			cpanel.showDetailPane();
		} else {
			mainInstance.map.closeExtInfoWindow();
			mainInstance.currentLocation = form.location.value;
			mainInstance.browseLocations(latlng, false);
		}
	});
}
MapHandler.prototype.browseLocations = function(center, initial) {
	var mainInstance = this;
	var radius = this.getRadius(initial);
	var searchURL = 'ajax/basenet.php?lat=' + center.lat() + '&lng=' + center.lng() + '&radius=' + radius;
	if (initial) { searchURL += '&order=alphabetical'; }
	GDownloadUrl(searchURL, function(data) {
		var xml = GXml.parse(data);
		var basepoints = xml.documentElement.getElementsByTagName('basepoint');
		mainInstance.map.clearOverlays();
		mainInstance.createTopPane(basepoints.length);
		var bounds = new GLatLngBounds();
		for (var i = 0; i < basepoints.length; i++) {
			var id = basepoints[i].getAttribute('id');
			var distance = parseFloat(basepoints[i].getAttribute('distance'));
			var point = new GLatLng(parseFloat(basepoints[i].getAttribute('lat')),
			                        parseFloat(basepoints[i].getAttribute('lng')));
			var type = parseInt(basepoints[i].getAttribute('type'));
			var time = parseInt(basepoints[i].getAttribute('time'));
			var marker = mainInstance.addMarker(id, point, mainInstance.getMapIcon(type, time));
			mainInstance.createBasepointEntry(marker, basepoints[i]);
			bounds.extend(point);
		}
		
		if (!bounds.isEmpty())
			mainInstance.map.setCenter(bounds.getCenter(),
			mainInstance.map.getBoundsZoomLevel(bounds));
		if (!initial)
			cpanel.showDetailPane();
	});
}
MapHandler.prototype.createTopPane = function(count) {
	var detailPane = cpanel.getDetailPane();
	var box = new Element('div', { 'class' : 'box-top' });
	detailPane.innerHTML = '';
	if (count == 0) {
		var message;
		message = 'Il n’y a pas de point service' +
		          ' dans un rayon de <b>' +	this.getRadius(false) +
		          'km</b>'
		if (this.currentLocation.indexOf(",") == -1) {
			message += '<br /><br /><span class="note">Veuillez entrer une' +
			           ' rue et un lieu séparés d’une virgule<br /><br />' +
			           ' p.ex. "Rue de la Gare, Lausanne "<br /><br />' +
			           'ou bien préciséz votre recherche p.ex.<br />"Fribourg' +
			           ' CH",<br />"5033 CH",<br />"Villeneuve VD"</span>'
		}
		box.update(message);
	} else {
		box.update('Nombre de points service affichés: <b>' + count + '</b>');
	}
	detailPane.appendChild(box);
}
MapHandler.prototype.createBasepointEntry = function(marker, basepoint) {
	var mainInstance = this;
	var detailPane = cpanel.getDetailPane();
	var outer = new Element('div', {
		'class' : 'box-outer',
		'id' : 'base_' + basepoint.getAttribute('id')
	});
	
	// Create Level Element Icon
	var attr = this.getIconAttributes(parseInt(basepoint.getAttribute('type')),
	                                  parseInt( basepoint.getAttribute('time')));
	var icon = new Element('img', {
		'width' : '28',
		'height' : '30',
		'alt' : attr._title,
		'title' : attr._title
	});
	icon.src = 'img/icon_details_transparent.gif';
	var level = new Element('div', { 'class' : 'box-level ' + attr._class }).update(icon);
	outer.appendChild(level);
	
	// Create Node Icon
	var icon = new Element('img', {
		'class' : 'left',
		'width' : '9',
		'height' : '9',
		'alt' : 'montrer sur la carte',
		'title' : 'montrer sur la carte'
	});
	icon.src = 'img/icon_box_more.png';
	outer.appendChild(icon);
	
	// add listener for anchor
	GEvent.addDomListener(icon, 'click', function() {
		GEvent.trigger(marker, 'click');
	});
	
	// Create inner-box Element
	var inner = new Element('div', { 'class' : 'box-inner' });
	var anchor = new  Element('a', {
		'class' : 'basepoint',
		'href' : '#',
		'title' : 'montrer sur la carte' }
	).update(basepoint.getAttribute('company'));
	GEvent.addDomListener(anchor, 'click', function() {
		GEvent.trigger(marker, 'click');
	});
	inner.appendChild(anchor);
	inner.appendChild(new Element('br', { }));
	if (basepoint.getAttribute('addition') != '') {
		inner.appendChild(document.createTextNode(
			basepoint.getAttribute('addition')
		));
		inner.appendChild(new Element('br', { }));
	}
	inner.appendChild(document.createTextNode(
		basepoint.getAttribute('box') + ' ' +
		basepoint.getAttribute('location')
	));
	inner.appendChild(new Element('br', { }));
	
	// adding inner pane to wrapper
	outer.appendChild(inner);
	
	// Create anchors (only if current location is set)
	if (this.currentLocation != null) {
		var address = this.currentLocation;
		var route = new Element('a', {
			'class' : 'route',
			'href' : '#',
			'title' : 'calculer la route' }
		).update('calculer la route');
		inner.appendChild(route);
		this.geocoder.getLatLng(address, function(latlng) {
			var printurl = 'http://maps.google.ch/maps?f=d&hl=fr&geocode=' +
			               '&saddr=' + latlng.lat() + ',' + latlng.lng() +
			               '&daddr=' + basepoint.getAttribute('lat') + ',' +
			               basepoint.getAttribute('lng') +
			               '&mra=pe&mrcr=0&ie=UTF8&z=12&pw=2';
			var toprint = new Element('a', {
				'href' : printurl,
				'title' : 'imprimer la route',
				'target' : '_blank' }
			).update('imprimer la route');
			inner.appendChild(toprint);
		});
		// Create Route display box
		var box_route = new Element('div', {
			'class' : 'box-route'
		});
		
		// adding listener for directions
		GEvent.addDomListener(route, 'click', function() {
			var address = mainInstance.currentLocation;
			box_route.innerHTML = '';
			mainInstance.map.closeExtInfoWindow();
			mainInstance.geocoder.getLatLng(address, function(latlng) {
				if (!latlng) {
					var p = new Element('p', { } ).update('La route ne peut pas ętre calculée.');
					box_route.appendChild(p);
				} else {
					var route = 'from: ' + latlng.lat() + ', ' + latlng.lng() +
					            ' to: ' + basepoint.getAttribute('lat') + ', ' +
					                      basepoint.getAttribute('lng');
					var directions = new GDirections(mainInstance.map, box_route);
					cpanel.markBasepoint(basepoint.getAttribute('id'));
					cpanel.showDirectionPanel(box_route);
					directions.load(route, { 'locale': 'fr' });
					// adding listener for directions load event
					GEvent.addListener(directions, 'load', function() {
						mainInstance.clearMarker(marker);
						mainInstance.clearDirections();
						mainInstance.currentDirections = directions;
					});
					// adding listener for directions error event
					GEvent.addListener(directions, 'error', function() {
						var p = new Element('p', { } ).update('La route ne peut pas ętre calculée.');
						box_route.appendChild(p);
					});
				}
			});
		});
		outer.appendChild(box_route);
	}
	// add clearer at bottom of each basepoint
	outer.appendChild(new Element('div', { 'class' : 'clear' } ));
	// add to detail pane
	detailPane.appendChild(outer);
}
MapHandler.prototype.clearMarker = function(marker) {
	if (this.currentMarker != null)
		this.map.addOverlay(this.currentMarker);
	if (marker != null)
		this.map.removeOverlay(marker);
	this.currentMarker = marker;
}
MapHandler.prototype.clearDirections = function() {
	if (this.currentDirections != null)
		this.currentDirections.clear();
}
MapHandler.prototype.getIconAttributes = function(type, time) {
	var cls = "icon_"; var title = "";
	cls += (type == 0) ? "mobil_" : "self_";
	title = (type == 0) ? "Mobil " : "ŕ emporter ";
	switch (time) {
		case 0: cls += "green"; title += "journée"; break;
		case 1: cls += "orange"; title += "24h"; break;
		case 2: cls += "violett"; title += "6h-22h"; break;
		default: cls += "none"; title = "";
	}
	return { _class: cls, _title: title };
}
MapHandler.prototype.getMapIcon = function(type, time) {
	var _color;
	var baseIcon = new GIcon();
	baseIcon.shadow = "img/icon_marker_shadow.png";
	baseIcon.iconSize = new GSize(20, 34);
	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 customIcon = new GIcon(baseIcon);
	var _type = (type == 0) ? 'mobil' : 'self';
	switch (time) {
		case 0:	_color = 'green'; break;
		case 1: _color = 'orange'; break;
		case 2: _color = 'violett'; break;
		default: _color = 'orange';
	}
	customIcon.image = 'img/icon_marker_' + _type + '_' + _color + '.png';
	return customIcon;
}

