﻿var map;
var dir;
var geo;
var destinationMarker;
	
var addressCache = new GGeocodeCache();

G_END_ICON.image = '/files/finavia/map/destination-marker.png';
G_END_ICON.transparent = '/files/finavia/map/destination-transparent.png';
G_END_ICON.printImage = '/files/finavia/map/destination-print.gif';
G_END_ICON.mozPrintImage = '/files/finavia/map/destination-print.gif';
G_END_ICON.shadow = null;
G_END_ICON.iconSize = new GSize(35, 35);
G_END_ICON.iconAnchor = new GPoint(13, 28);
G_END_ICON.infoWindowAnchor = G_END_ICON.iconAnchor;
G_END_ICON.imageMap = [ 18,27, 12,31, 1,19, 6,15, 0,12, 2,5, 20,5, 25,0, 33,0, 33,8, 28,13, 28,31, 20,32 ];

G_START_ICON.image = '/files/finavia/map/start-marker.png';
G_START_ICON.transparent = '/files/finavia/map/start-transparent.png';
G_START_ICON.printImage = '/files/finavia/map/start-print.gif';
G_START_ICON.mozPrintImage = '/files/finavia/map/start-print.gif';
G_START_ICON.shadow = null;
G_START_ICON.iconSize = new GSize(28, 44);
G_START_ICON.iconAnchor = new GPoint(25, 43);
G_START_ICON.infoWindowAnchor = G_START_ICON.iconAnchor;
G_START_ICON.imageMap = [ 22,22, 17,20, 5,24, 0,21, 0,1, 5,4, 13,1, 28,0, 28,44, 22,44 ];

var airportIcon = new GIcon(G_END_ICON);

function registerAirport(name, info, point)
{ 
	addressCache.put(name, {
		name : name,
		info : info,
		nameWithCoords : name + " @" + point.lat + "," + point.lng,
		Status : {
			code : 200,
			request : 'geocode'
		},
		Placemark : [
			{
				address : name,
				Point : {
					coordinates: [ point.lng, point.lat, 0]
				}
			}
		]
	});
}

function createAirportMarker(name)
{
	var cached = addressCache.get(name);
	
	if (!cached)
	{
		return null;
	}
	
	var place = cached.Placemark[0];
	
	var point = new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
	
	var marker = new GMarker(point, { icon : airportIcon });
	
	GEvent.addListener(marker, 'click', function()
	{
		marker.openInfoWindowHtml(cached.info || name);
	});
	
	map.addOverlay(marker);
		
	return marker;
}

function disableScrollingWhileZooming()
{
	var cont = map.getContainer();
	
	var wheelHandler = function(e)
	{
		if (!e)
		{
			e = window.event;
		}
		
		if (e.preventDefault)
		{
			e.preventDefault();
		}
		
		e.returnValue = false;
	}
	
	GEvent.addDomListener(cont, "DOMMouseScroll", wheelHandler);
	
	cont.onmousewheel = wheelHandler;
}

window.addEvent('domready', function()
{
	if (!GBrowserIsCompatible())
	{
		return;
	}
	
	geo = new GClientGeocoder();
	geo.setBaseCountryCode('fi');
	geo.setCache(addressCache);
	
	map = new GMap2(document.getElementById('canvas'));
	map.setCenter(new GLatLng(65.42173, 26.367188), 4);
	map.addControl(new GLargeMapControl());
	map.enableScrollWheelZoom();
	
	disableScrollingWhileZooming();
	
	dir = new GDirections(map);
	
	GEvent.addListener(dir, 'load', function()
	{
		if (dir.getNumRoutes() < 1)
		{
			return;
		}
		
		var container = $('direction-list');
		var route = dir.getRoute(0);
		
		while (container.firstChild) {
			container.removeChild(container.firstChild);
		}
		
		$('total').setHTML(route.getDistance().html + ' - tietoja ' + route.getDuration().html);
		
		var steps = route.getNumSteps();
		
		for (var i = 0; i < steps; ++i)
		{
			var step = route.getStep(i);
			
			var cstep = new Element('td', { 'class' : 'cstep' });
			cstep.setText((i + 1) + '.');
			
			var cdesc = new Element('td', { 'class' : 'cdescription' });
			cdesc.setHTML(step.getDescriptionHtml());
			
			var cdist = new Element('td', { 'class' : 'cdistance' });
			cdist.setHTML(step.getDistance().html);
			
			container.adopt(new Element('tr')
				.adopt(cstep)
				.adopt(cdesc)
				.adopt(cdist)
			);
		}
		
		$('directions').setStyle('display', 'block');
	});
	
	GEvent.addListener(dir, 'error', function()
	{
		handleError(dir.getStatus().code);
	});
	
	restoreLocation();
});

function restoreLocation()
{
	var from = hashString('start');
	var to = hashString('airport');
	
	var istart = $('istart');
	var dest = $('idestination');
	
	istart.value = from || '';
	
	var opts = dest.options;
	
	for (var i = 0; i < opts.length; ++i)
	{
		if (opts[i].value == to)
		{
			dest.selectedIndex = i;
			
			break;
		}
	}
	
	searchRoute();
}

function hideError() 
{
	if (handleError.tooltip)
	{
		handleError.tooltip.destroy();
		
		delete handleError.tooltip;
	}
}

function handleError(code)
{
	hideError();
	
	var istart = $('istart');
	var coords;
	
	if (istart.offsetWidth > 0)
	{
		coords = istart.getCoordinates();
	}
	else
	{
		coords = istart.getParent().getCoordinates();
	}
	
	if (istart.clientLeft && istart.clientLeft < istart.offsetLeft)
	{
		var diff = (istart.offsetLeft - istart.clientLeft);
		
		coords.left -= diff;
		coords.right -= diff;
	}
	
	var styles = {
		left : coords.right - 20,
		top : coords.top - coords.height / 2
	};
	
	var msg = '';
	
	switch (code)
	{
		case G_GEO_SUCCESS:
			return;
		case G_GEO_BAD_REQUEST:
			msg = 'Palvelin palautti virheellisen tuloksen.';
			break;
		case G_GEO_SERVER_ERROR:
			msg = 'Palvelimella tapahtui virhe.';
			break;
		case G_GEO_MISSING_QUERY:
			msg = 'Osoite puuttuu.';
			break;
		case G_GEO_MISSING_ADDRESS:
			msg = 'Osoite puuttuu.';
			break;
		case G_GEO_UNKNOWN_ADDRESS:
			var istart = $('istart');
			if (!/ (\d+)$/.test(istart.value))
			{
				istart.value += ' 1';
				
				searchRoute();
				
				return;
			}
			msg = 'Antamaasi osoitetta ei löytynyt.';
			break;
		case G_GEO_UNAVAILABLE_ADDRESS:
			msg = 'Osoitetta ei voida näyttää.';
			break;
		case G_GEO_UNKNOWN_DIRECTIONS:
			msg = 'Reitin laskenta ei onnistunut.';
			break;
		case G_GEO_BAD_KEY:
			msg = 'Google Maps API:n avain ei kelpaa.';
			break;
		case G_GEO_TOO_MANY_QUERIES:
			msg = 'Palvelu on tilapäisesti poissa käytöstä kuormituksen vuoksi.';
			break;
		default:
			msg = 'Hups! Nyt tapahtui virhe.';
	}
	
	arguments.callee.tooltip = new Tooltip(msg, styles);
}

function hideSuggestions()
{
	new Fx.Styles($('placesuggestions'), {
		duration : 250,
		transition : Fx.Transitions.Expo.easeOut
	})
	.start({
		opacity : 0
	});
}

function showSuggestions(geoResponse)
{	
	var textbox = $('istart');
	var box = $('placesuggestions');
	
	box.getElements('li').each(function(li)
	{
		if (!li.hasClass('title'))
		{
			li.parentNode.removeChild(li);
		}
	});
	
	var placemarks = geoResponse.Placemark;
	
	if (!placemarks)
	{
		return;
	}
	
	placemarks.each(function(placemark)
	{
		var li = new Element('li');
		
		var name;
		
		try
		{
		    switch (placemark.AddressDetails.Accuracy)
		    {
			    case 0: // unknown
				    name = 'Tuntematon sijanti @' + placemark.Point.coordinates[0] + ',' + placemark.Point.coordinates[1];
				    break;
			    case 1: // country
				    name = placemark.address;
				    break;
			    case 2: // region
				    name = placemark.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName;
				    break;
			    case 3: // sub-region
				    name = placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.SubAdministrativeAreaName;
				    break;
			    case 4: // town
				    name = placemark.AddressDetails.Country.AdministrativeArea.Locality.LocalityName;
				    break;
			    case 5: // post code
			    
				    var loc = placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality;
				    
				    if (loc.DependentLocality)
				    {
					    name = loc.DependentLocality.PostalCode.PostalCodeNumber + ' ' + loc.DependentLocality.DependentLocalityName;
				    }
				    else
				    {
					    name = loc.PostalCode.PostalCodeNumber + ' ' + loc.LocalityName;
				    }
				    
				    break;
			    case 6: // street
			    case 7: // intersection
			    
				    var loc = placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality;
				    
				    if (loc.DependentLocality)
				    {
					    name = loc.DependentLocality.DependentLocalityName + ', ' + loc.DependentLocality.Thoroughfare.ThoroughfareName;
				    }
				    else
				    {
					    name = loc.LocalityName + ', ' + loc.Thoroughfare.ThoroughfareName;
				    }
				    
				    break;
			    case 8: // address
			    
				    var loc = placemark.AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality;
				    
				    if (loc.DependentLocality)
				    {
					    name = loc.DependentLocality.DependentLocalityName + ', ' +
						    loc.DependentLocality.Thoroughfare.ThoroughfareName.replace(/^(\d+) (.+)/, function(all, num, street)
						    {
							    return street + ' ' + num;
						    });
				    }
				    else
				    {
					    name = loc.LocalityName + ', ' +
						    loc.Thoroughfare.ThoroughfareName.replace(/^(\d+) (.+)/, function(all, num, street)
						    {
							    return street + ' ' + num;
						    });
				    }
				    
				    break;
		    }
		}
		catch (e)
		{
		    handleError(G_GEO_UNKNOWN_ADDRESS);
		    
		    return;
		}
		
		li.setText(name);
		
		box.appendChild(li);
		
		li.addEvent('click', function()
		{
			textbox.value = placemark.address;
			
			box.setStyles({
				opacity : 1,
				display : 'block'
			});
			
			searchRoute();
		});
		
		var fx = new Fx.Styles(li, { duration : 250, wait : false });
			
		li.addEvent('mouseenter', function()
		{
			fx.start({
				'background-color' : '#e0e0e0'
			});
		});
		
		li.addEvent('mouseleave', function()
		{
			fx.start({
				'background-color' : '#ffffff'
			});
		});
	});
	
	box.setStyles({
		opacity : 0,
		display : 'block'
	});
	
	new Fx.Styles(box, {
		duration : 250,
		transition : Fx.Transitions.Expo.easeOut
	})
	.start({
		opacity : 1
	});
}

function fetchRoute(from, to)
{
	dir.load('from: ' + from + ' to: ' + to, {
		locale : 'fi_FI',
		getSteps : true
	});
}

function hideRoute()
{
	dir.clear();
	$('directions').setStyle('display', 'none');
}

function searchRoute()
{
	if (destinationMarker)
	{
		map.removeOverlay(destinationMarker);
		
		destinationMarker = null;
	}
	
	hideRoute();
	hideSuggestions();
	hideError();
	
	var from = $('istart').value;
	var to = $('idestination').value;
	var cached = addressCache.get(to);
	
	if (from.length < 1)
	{
		moveToDestination();
		
		$('istart').focus();
		
		return false;
	}
	
	window.location.hash = 'start=' + encodeURIComponent(from) + '&airport=' + encodeURIComponent(to);
	
	if (cached && cached.nameWithCoords)
	{
		to = cached.nameWithCoords;
	}
	
	geo.getLocations(from, function(response)
	{
		if (response.Status.code != G_GEO_SUCCESS)
		{
			handleError(response.Status.code);
			
			return;
		}
		
		var size = response.Placemark.length;
		
		if (size == 1)
		{
			fetchRoute(from, to);
		}
		else if (size > 1)
		{
			showSuggestions(response);
		}
		else
		{
		}
	});
	
	return false;
}

function moveToDestination()
{
	var to = $('idestination').value;
	
	var cached = addressCache.get(to);
	
	destinationMarker = createAirportMarker(to, cached ? cached.info : null);
	
	window.location.hash = 'airport=' + encodeURIComponent(to);
	
	geo.getLocations(to, function(response)
	{
		if (!response || response.Status.code != 200)
		{
			return null;
		}
		
		var place = response.Placemark[0];
		
		map.setCenter(new GLatLng(place.Point.coordinates[1], place.Point.coordinates[0]));
	});
}

function queryString(name)
{
	if (!window._queryString)
	{
		window._queryString = {};
		
		if (!location.search) {
			return null;
		}
		
		var parts = location.search.substring(1).split('&');
			
		parts.each(function(part)
		{
			var pair = part.split('=', 2);
			
			if (pair.length == 2)
			{
				window._queryString[pair[0]] = decodeURIComponent(pair[1].replace(/\+/g, ' '));
			}
		});
	}
	
	return window._queryString[name];
}

function hashString(name)
{
	if (!window._hash)
	{
		window._hash = {};
		
		if (!location.hash) {
			return null;
		}
		
		var parts = location.hash.substring(1).split('&');
			
		parts.each(function(part)
		{
			var pair = part.split('=', 2);
			
			if (pair.length == 2)
			{
				window._hash[pair[0]] = decodeURIComponent(pair[1].replace(/\+/g, ' '));
			}
		});
	}
	
	return window._hash[name];
}
