// default error texts (these vars can be changed for making it language independant)
var strErrorCodeTextInvalidData         = 'De route kan niet worden berekend. Dit kan komen omdat er geen route is, GoogleMaps geen data heeft voor het eindpunt van de route, of er contractuele beperkingen zijn op de aanwezige data.';
var strErrorCodeTextInvalidInputData    = 'De route kan niet worden berekend. Check of het vanaf adres klopt. Als dit zo is, kan het probleem zijn dat het startpunt of het eindpunt nog niet bij Google Maps bekend is.';
var strErrorCodeTextLimitQueryExceeded  = 'Er is een fout opgetreden. Probeer het later nog eens.';
var strErrorCodeTextUnhandled           = 'Er is een fout opgetreden.';

var Searchmap = function($) {
    var config = {
        /**
        * Do we need to show custom icons instead of default Google's or not.
        * If we do, 6 icons need to be provided with paths like "/images/googlemaps/marker_single.png" (see getIcon)
        * Does not affect clustered markers (see getZoomIcon, getLocIcon) yet. There are no any 'default icons' for them.
        * Support for them can be added e.g. by making customIcons setting accept both boolean and an object literal {customIcons = {zoom:true}}
        */
        customIcons: true,
        popupSelected: false,
		enableMapTypeControl: true,
		enableOverviewControl: true,
		enableScaleControl: true,
		enableLargeMapControl: true,
		enableSmallMapControl: false,
		draggable: true,
		disableDoubleClickZoom: false,
		showLoader: false
    };

    var priv = {
        minZoom: 4,
        maxZoom: 18,
        defaultLat: 33.57,
        defaultLng: 10.28,
        defaultZoom: 4,

        pathPrefix: Resource.GetText('path_prefix'),
        cookiePrefix: Resource.GetTextForCookie('cookie-prefix'),
        query: '',
        googleMap: null,
        markerManager: null,
        updateMapTimeout: null,
        currentId: -1,
        // Google maps query for destination place. E.g. 'Barcelona, Spain'
        routeTo: null,

        // labels
        labelReviewRating: Resource.GetText('compare_reviewrating'),
        labelMoreAbout: Resource.GetText('more_about'),
        labelSearchPage: 'zoeken.aspx',

        getHashValue: function(href, key) {
            var hashString = '';
            var params = new Array();

            if (href == null) {
                href = location.href;
            }

            if (href.indexOf('#') != -1) {
                hashString = href.split('#')[1];
            }

            if (hashString.indexOf("&") != -1) {
                params = hashString.split("&");
            }
            else if (hashString.indexOf("=") != -1) {
                params[params.length] = hashString;
            }

            for (var j = 0; j < params.length; j++) {
                param = params[j].split("=");
                if (param[0] == key) {
                    return param[1];
                }
            }

            return '';
        },

        getMarkerValue: function(markerObj, value) {
            if (markerObj != null && markerObj.getAttribute(value)) {
                return markerObj.getAttribute(value);
            }
            else {
                return '';
            }
        },

        getIcon: function(isMultiple, isSelected) {
            var icon = new GIcon();
            if (isMultiple) {
                if (isSelected) {
                    icon.image = priv.pathPrefix + "/images/googlemaps/marker_multiple-sel.png";
                } else {
                    icon.image = priv.pathPrefix + "/images/googlemaps/marker_multiple.png";
                }
                icon.iconAnchor = new GPoint(27, 23);
                icon.iconSize = new GSize(54, 47);
            } else {
                if (isSelected) {
                    icon.image = priv.pathPrefix + "/images/googlemaps/marker_single-sel.png";
                } else {
                    icon.image = priv.pathPrefix + "/images/googlemaps/marker_single.png";
                }
                icon.iconAnchor = new GPoint(19, 19);
                icon.iconSize = new GSize(39, 38);
            }

            return icon;
        },

        getZoomIcon: function(markerCount, hover) {
            var markerSize = 28;
            if (markerCount > 999) {
                markerSize = 60;
            } else if (markerCount > 99) {
                markerSize = 44;
            } else if (markerCount > 9) {
                markerSize = 36;
            }

            var icon = new GIcon();
            icon.image = priv.pathPrefix + '/images/googlemaps/marker' + markerSize + 'x' + markerSize + hover + '.png';
            icon.iconSize = new GSize(markerSize, markerSize);
            icon.iconAnchor = new GPoint((markerSize / 2), (markerSize / 2));

            return icon;
        },

        getLocIcon: function(markerLength) {
            var markerSize = 100;
            if (markerLength > 18) {
                markerSize = 183;
            } else if (markerLength > 15) {
                markerSize = 146;
            } else if (markerLength > 13) {
                markerSize = 122;
            }

            var icon = new GIcon();
            icon.image = priv.pathPrefix + '/images/googlemaps/loc-marker-' + markerSize + '.png';
            icon.iconSize = new GSize(markerSize, 22);
            icon.iconAnchor = new GPoint(0, 0);

            return icon;
        },

        createPopupMarker: function(gllPosition, markerObjArr) {
            //create marker with popup
            var isMultiple = false;
            var isSelected = false;
            if (markerObjArr.length > 1) {
                isMultiple = true;
                for (var i = 0; i < markerObjArr.length; i++) {
                    if (priv.currentId == parseInt(markerObjArr[i].getAttribute('objectid'))) {
                        isSelected = true;
                        break;
                    }
                }
            } else {
                if (priv.currentId == parseInt(markerObjArr[0].getAttribute('objectid'))) {
                    isSelected = true;
                }
            }
            var opts = {};
            if (config.customIcons) {
                var icon = priv.getIcon(isMultiple, isSelected);
                $.extend(opts, { "icon": icon });
            }
            var marker = new GMarker(gllPosition, opts);
            //markerObjArr is the full set of properties that have been created in XML... tooltip takes care of display issues
            if (!(!isMultiple && (isSelected && !config.popupSelected))) {
                GEvent.addListener(marker, 'click', function() {
                    var detailContent = '';
                    var fotoContent = '';
                    var objectMax = 2;
                    var rangequery = '';
                    for (var i = 0; i < markerObjArr.length && i < objectMax; i++) {
                        var detailUrl = priv.getMarkerValue(markerObjArr[i], "linkurl");
                        var title = priv.getMarkerValue(markerObjArr[i], "title");
                        var mainImage = priv.getMarkerValue(markerObjArr[i], "imageurl");
                        var price = priv.getMarkerValue(markerObjArr[i], "price");
                        var starRating = priv.getMarkerValue(markerObjArr[i], "stars");
                        var cityregioncountry = priv.getMarkerValue(markerObjArr[i], "cityregioncountry");
                        var usp = priv.getMarkerValue(markerObjArr[i], "usp");
                        var reviewrating = priv.getMarkerValue(markerObjArr[i], "reviewrating");
                        var images = priv.getMarkerValue(markerObjArr[i], "images");
                        rangequery = priv.getMarkerValue(markerObjArr[i], "rangequery");

                        var pricetag = '';
                        if (price != '') {
                            pricetag = '<div class="tooltip-pricetag">' + Resource.GetText('result_from') + ' <span class="tooltip-price">&euro;' + price + '</span></div>';
                        }

                        detailContent += '<div class="tooltip-main-image"><a href="' + detailUrl + '" target="_top"><img border="0" alt="' + title + '" src="' + mainImage + '"/></a></div>' +
			                    '<div class="tooltip-info">' +
					                '<a href="' + detailUrl + '" target="_top">' + title + '</a><span class="star-rating star-rating-' + starRating + '">' + Resource.GetText('stars') + '</span>' +
					                '<span class="locale">' + cityregioncountry + '</span>';
                        if (reviewrating != 0) // if rating is not provided at all, also hide review ratings (see SMIGR-418)
                        {
                            detailContent += '<span class="row text">' + priv.labelReviewRating + ' <span class="reviewrating">' + reviewrating + '</span></span>';
                        }
                        detailContent += '<div class="accorow"><div class="tooltip-head"><a href="' + detailUrl + '" target="_top">&gt; ' + priv.labelMoreAbout + ' ' + title + '</a></div>' +
			                    '</div>' +
			                    '<div class="clear-both"></div>' +
			                    pricetag +
			                    '</div></div><div class="clear-both"></div>';

                        if (images == '') {
                            fotoContent += '<div class="accorow"><div class="tooltip-head"><a href="' + detailUrl + '" target="_top">&gt; ' + priv.labelMoreAbout + ' ' + title + '</a></div>' + Resource.GetText('no_photos') + '</div>';
                        } else {
                            var arrImages = images.split(',');
                            fotoContent += '<div class="accorow">';
                            for (var j = 0; j < arrImages.length; j++) {
                                fotoContent += '<div class="tooltip-main-image"><img border="0" alt="' + title + '" src="' + arrImages[j] + '"/></div>';
                            }
                            fotoContent += '<div class="tooltip-head"><a href="' + detailUrl + '" target="_top">&gt; ' + priv.labelMoreAbout + ' ' + title + '</a></div>';
                            fotoContent += '</div>';
                        }
                    }
                    if (markerObjArr.length > objectMax) {
                        detailContent += '<div class="accorow"><a href="' + priv.pathPrefix + '/' + priv.labelSearchPage + '?' + rangequery + '" target="_top">meer (' + markerObjArr.length + ')</a></div>';
                    }
                    var infoTabs = [new GInfoWindowTab(Resource.GetText('details'), detailContent),
                                    new GInfoWindowTab(Resource.GetText('photos'), fotoContent)];
                    priv.googleMap.openInfoWindowTabs(gllPosition, infoTabs);
                });
            }

            return marker;
        },

		createLinkMarker: function(gllPosition, strTargetText, strTargetLink, strMarkerToolTip) {
			//Get rid of HTML tags and the 1000s separator or it will give problems when parsed
			var intMarkerCount = strTargetText.replace(".", "");
			var marker = null;

			var locationMarkerText = "<nobr>" + strMarkerToolTip + "</nobr>";
			var otherOpts = { "labelClass": "locationLabel", "icon": priv.getLocIcon((strMarkerToolTip + " (" + strTargetText + ")").length), "clickable": true, "draggable": false, "labelText": locationMarkerText, "labelOffset": new GSize(15, 0), "title": strMarkerToolTip };

			marker = new LabeledMarker(gllPosition, otherOpts);
			//add click event... zoom in
			if (config.draggable) {
				GEvent.addListener(marker, 'click', function() {
					location.href = strTargetLink;
				});
			}

			//mouseover and mouseout make the marker change color when the mouse is over it
			GEvent.addListener(marker, 'mouseover', function() {
				priv.googleMap.disableDragging();
			});
			GEvent.addListener(marker, 'mouseout', function() {
				if (config.draggable) {
					priv.googleMap.enableDragging();
				}
			});


			return marker;
		},

        createZoomMarker: function(gllPosition, strTargetText, intTargetZoom, strMarkerToolTip) {
            //Get rid of HTML tags and the 1000s separator or it will give problems when parsed
            var intMarkerCount = strTargetText.replace(".", "");
            var marker = null;

            if (strMarkerToolTip == Resource.GetText('map_clicktozoom')) {
                var opts = { "icon": priv.getZoomIcon(intMarkerCount, 'n'), "clickable": true, "draggable": false, "labelText": strTargetText, "labelOffset": new GSize(-23, -19), "title": strMarkerToolTip };
                var strHoverImage = priv.getZoomIcon(intMarkerCount, 'h').image;
                var strNoHoverImage = priv.getZoomIcon(intMarkerCount, 'n').image;

                marker = new LabeledMarker(gllPosition, opts);
                //add click event... zoom in
				if (config.draggable) {
                GEvent.addListener(marker, 'click', function() {
                    priv.zoomToLocation(gllPosition.lat(), gllPosition.lng(), intTargetZoom);
                    priv.googleMap.enableDragging();
                });
				}

                //mouseover and mouseout make the marker change color when the mouse is over it
                GEvent.addListener(marker, 'mouseover', function() {
                    marker.setImage(strHoverImage);
                    marker.setTextColor("#ff6600");
                    priv.googleMap.disableDragging();
                });
                GEvent.addListener(marker, 'mouseout', function() {
                    marker.setImage(strNoHoverImage);
                    marker.setTextColor("#ffffff");
					if (config.draggable) {
                    priv.googleMap.enableDragging();
					}
                });
            } else {
                var locationMarkerText = "<nobr>" + strMarkerToolTip + " (" + strTargetText + ")</nobr>";
                var otherOpts = { "labelClass": "locationLabel", "icon": priv.getLocIcon((strMarkerToolTip + " (" + strTargetText + ")").length), "clickable": true, "draggable": false, "labelText": locationMarkerText, "labelOffset": new GSize(15, 0), "title": strMarkerToolTip };

                marker = new LabeledMarker(gllPosition, otherOpts);
                //add click event... zoom in
				if (config.draggable) {
                GEvent.addListener(marker, 'click', function() {
                    priv.zoomToLocation(gllPosition.lat(), gllPosition.lng(), intTargetZoom);
                    priv.googleMap.enableDragging();
                });
				}

                //mouseover and mouseout make the marker change color when the mouse is over it
                GEvent.addListener(marker, 'mouseover', function() {
                    priv.googleMap.disableDragging();
                });
                GEvent.addListener(marker, 'mouseout', function() {
					if (config.draggable) {
                    priv.googleMap.enableDragging();
					}
                });
            }

            return marker;
        },

        setHistoryCookie: function() {
            $.cookie(priv.cookiePrefix + "searchmap", priv.googleMap.getCenter().lat() + '^' + priv.googleMap.getCenter().lng() + '^' + priv.googleMap.getZoom(), { expires: 1, path: '/' });
        },

        zoomToLocation: function(fltLat, fltLng, intZoom) {
            priv.googleMap.setCenter(new GLatLng(fltLat, fltLng), intZoom);
        },

		createMap: function(lat, lng, z, mapType, markersXml) {
			if (config.enableLargeMapControl) {
            priv.googleMap.addControl(new GLargeMapControl());
			}
			if (config.enableSmallMapControl) {
				priv.googleMap.addControl(new GSmallMapControl());
			}
			if (config.enableMapTypeControl) {
            priv.googleMap.addControl(new GMapTypeControl());
			}
			if (config.enableScaleControl) {
            priv.googleMap.addControl(new GScaleControl());
			}
            if (config.enableOverviewControl) {
            priv.googleMap.addControl(new GOverviewMapControl());
			}
            priv.googleMap.setCenter(new GLatLng(lat, lng), z);
			if (!config.disableDoubleClickZoom) {
            priv.googleMap.enableDoubleClickZoom();
			}
			if (!config.draggable) {
				priv.googleMap.disableDragging();
			}

            // use normal map as default map type
            mapType = mapType || G_NORMAL_MAP;
            priv.googleMap.setMapType(mapType);

            // limit zooming
            var mapTypes = priv.googleMap.getMapTypes();
            for (var i in mapTypes) {
                mapTypes[i].getMinimumResolution = function() { return priv.minZoom; };
                mapTypes[i].getMaximumResolution = function() { return priv.maxZoom; };
            }

            // Set googlemaps events
            GEvent.addListener(priv.googleMap, 'zoomend', function() {
                if (priv.updateMapTimeout != null) {
                    window.clearTimeout(priv.updateMapTimeout);
                }
                priv.updateMapTimeout = setTimeout('Searchmap.updateMap()', 150);
            });
            GEvent.addListener(priv.googleMap, 'dragend', function() {
                if (priv.updateMapTimeout != null) {
                    window.clearTimeout(priv.updateMapTimeout);
                }
                priv.updateMapTimeout = setTimeout('Searchmap.updateMap()', 150);
            });
            GEvent.addListener(priv.googleMap, 'moveend', function() {
                // add current search to cookie
                priv.setHistoryCookie();
            });

            var markerMgrOptions = { minZoom: priv.minZoom, maxZoom: priv.maxZoom, trackMarkers: false };
            priv.markerManager = new MarkerManager(priv.googleMap, markerMgrOptions);

			if (markersXml != undefined && markersXml != '') {
				priv.setMarkers(GXml.parse(markersXml));
			}
			else {
            // Update the map with markers
            priv.query = priv.getHashValue(location.href, 'query');
            Searchmap.updateMap();
        }
		},

		setMarkers: function(xmlDoc) {
                    var resultCount = xmlDoc.documentElement.getAttribute("resultcount");
                    $('#resultCount').html(String.format(Resource.GetText('result_type_found_search'), resultCount));

                    // load the markers
                    var arrGroupMarkers = [];
                    var arrMarkers = [];
                    var fltCurrLat = 0;
                    var fltCurrLng = 0;
                    var markersXml = xmlDoc.documentElement.getElementsByTagName("marker");
                    for (var i = 0; i < markersXml.length; i++) {
                        var fltMarkerLat = parseFloat(markersXml[i].getAttribute("lat"));
                        var fltMarkerLng = parseFloat(markersXml[i].getAttribute("lng"));
                        var gllPoint = new GLatLng(fltMarkerLat, fltMarkerLng);
                        var name = markersXml[i].getAttribute("name");
                        var intMarkerClass = markersXml[i].getAttribute("jump");
                        var strMarkerText = markersXml[i].getAttribute("text");

                        if (intMarkerClass == '1') {
                            if (i > 0 && arrGroupMarkers.length > 0) {
                                //if not the same, flush and reset arrGroupMarkers
                                arrMarkers.push(priv.createPopupMarker(new GLatLng(fltCurrLat, fltCurrLng), arrGroupMarkers));
                                arrGroupMarkers = new Array();
                            }

                            //zoom marker... this one zooms in when clicked
                            var intMarkerZoom = parseInt(markersXml[i].getAttribute("zoom"));
                            var strMarkerToolTip = markersXml[i].getAttribute("tooltip");

                            //create empty bound box
                            var gllbBounds = new GLatLngBounds();

                            //get all vars for the two points
                            var fltTopLeftLat = parseFloat(markersXml[i].getAttribute("tllat"));
                            var fltTopLeftLon = parseFloat(markersXml[i].getAttribute("tllon"));
                            var fltBotRightLat = parseFloat(markersXml[i].getAttribute("brlat"));
                            var fltBotRightLon = parseFloat(markersXml[i].getAttribute("brlon"));

                            //create top left and bottom right points
                            var gllTopLeft = new GLatLng(fltTopLeftLat, fltTopLeftLon);
                            var gllBotRight = new GLatLng(fltBotRightLat, fltBotRightLon);

                            //add to bound box
                            gllbBounds.extend(gllTopLeft);
                            gllbBounds.extend(gllBotRight);

                            //if all went OK, the box will contain the marker
                            //if not, we use the zoom that has been set on the marker before creating
                            //the bound box. (preset in Web.config)
                            if (gllbBounds.contains(gllPoint)) {
                                //set zoom to what the map thinks it should be
                                intMarkerZoom = priv.googleMap.getBoundsZoomLevel(gllbBounds);
                                //if we are not moving up relative to current view
                                //force zoom in
						var currentzoom = priv.googleMap.getZoom();
						if (intMarkerZoom <= currentzoom) {
							var intCurrentZoom = currentzoom;
                                    intMarkerZoom = intCurrentZoom + 1;
                                }
                            }
                            arrMarkers.push(priv.createZoomMarker(gllPoint, strMarkerText, intMarkerZoom, strMarkerToolTip));
                        }
				else if (intMarkerClass == 2) {
					//link marker, this links to a url outside of the map
					if (i > 0 && arrGroupMarkers.length > 0) {
						//if not the same, flush and reset arrGroupMarkers
						arrMarkers.push(priv.createPopupMarker(new GLatLng(fltCurrLat, fltCurrLng), arrGroupMarkers));
						arrGroupMarkers = new Array();
					}


					var strMarkerToolTip = markersXml[i].getAttribute("tooltip");
					var strMarketUrl = markersXml[i].getAttribute("linkurl");

					//create empty bound box
					var gllbBounds = new GLatLngBounds();

					//get all vars for the two points
					var fltTopLeftLat = parseFloat(markersXml[i].getAttribute("tllat"));
					var fltTopLeftLon = parseFloat(markersXml[i].getAttribute("tllon"));
					var fltBotRightLat = parseFloat(markersXml[i].getAttribute("brlat"));
					var fltBotRightLon = parseFloat(markersXml[i].getAttribute("brlon"));

					//create top left and bottom right points
					var gllTopLeft = new GLatLng(fltTopLeftLat, fltTopLeftLon);
					var gllBotRight = new GLatLng(fltBotRightLat, fltBotRightLon);

					//add to bound box
					gllbBounds.extend(gllTopLeft);
					gllbBounds.extend(gllBotRight);

					arrMarkers.push(priv.createLinkMarker(gllPoint, strMarkerText, strMarketUrl, strMarkerToolTip));
				}
                        else {
                            if (fltMarkerLat != fltCurrLat || fltMarkerLng != fltCurrLng) {
                                if (i > 0 && arrGroupMarkers.length > 0) {
                                    //if not the same, flush and reset arrGroupMarkers
                                    arrMarkers.push(priv.createPopupMarker(new GLatLng(fltCurrLat, fltCurrLng), arrGroupMarkers));
                                    arrGroupMarkers = new Array();
                                }
                                //set current lat lng
                                fltCurrLat = fltMarkerLat;
                                fltCurrLng = fltMarkerLng;
                            }

                            //add to current group
                            arrGroupMarkers.push(markersXml[i]);

                            //if last run flush
                            if ((i + 1) >= markersXml.length) {
                                arrMarkers.push(priv.createPopupMarker(new GLatLng(fltCurrLat, fltCurrLng), arrGroupMarkers));
                            }
                        }
                    }
			if (config.showLoader) {
				$('#googleMapLoader').hide();
			}
                    priv.markerManager.clearMarkers();
                    priv.markerManager.addMarkers(arrMarkers, priv.minZoom, priv.maxZoom);
                    priv.markerManager.refresh();

                    // load the refinements
                    //                    var refinements = xmlDoc.documentElement.getElementsByTagName("refinements")[0].childNodes[0].nodeValue;
                    //                    $('#nav').html(refinements);
                    //                    $('#navigation ul.navigation a, #selection ul a').bind('click', function()
                    //                    {
                    //                        Searchmap.facetClick($(this).attr('href'));
                    //                    });
                }
	};

	return {
		updateMap: function() {
			Log.Debug('lat:' + priv.googleMap.getCenter().lat() + ', lng:' + priv.googleMap.getCenter().lng() + ', zoom:' + priv.googleMap.getZoom());

			// close open tooltips
			priv.googleMap.closeInfoWindow();

			if (config.showLoader) {
				priv.markerManager.clearMarkers();
				$('#googleMapLoader').show();
			}

			// Get map variables
			var currentZoom = priv.googleMap.getZoom();
			var bounds = priv.googleMap.getBounds();
			var gllCenter = priv.googleMap.getCenter();

			var gLatLngHeight2 = new GLatLng(bounds.getNorthEast().lat(), bounds.getSouthWest().lng());
			var gLatLngHeight3 = new GLatLng(bounds.getSouthWest().lat(), bounds.getNorthEast().lng());
			var gLatLngWidth2 = new GLatLng(bounds.getSouthWest().lat(), bounds.getNorthEast().lng());
			var gLatLngWidth3 = new GLatLng(bounds.getNorthEast().lat(), bounds.getSouthWest().lng()) 

			var height2 = bounds.getSouthWest().distanceFrom(gLatLngHeight2);
			var height3 = bounds.getNorthEast().distanceFrom(gLatLngHeight3);

			var width2 = bounds.getSouthWest().distanceFrom(gLatLngWidth2);
			var width3 = bounds.getNorthEast().distanceFrom(gLatLngWidth3);

			var width = width2 > width3 ? width2 : width3;
			var height = height2 > height3 ? height2 : height3;
			var locationType = $('#locationType').length > 0 ? $('#locationType').val() : '';
			var locationId = $('#cityId').length > 0 ? $('#cityId').val() : -1;
			var markerSource = $('#markerSource').length > 0 ? $('#markerSource').val() : '';

			locationId = locationId == -1 ? ($('#regionId').length > 0 ? $('#regionId').val() : -1) : locationId;
			locationId = locationId == -1 ? ($('#countryId').length > 0 ? $('#countryId').val() : -1) : locationId;

			// Build markers xml url
			var url = priv.pathPrefix + '/js/ajax/loadmap.ashx?' +
		              'lat=' + gllCenter.lat() +
		              '&lng=' + gllCenter.lng() +
		              '&zoomlevel=' + currentZoom +
		              '&width=' + width +
		              '&height=' + height +
		              '&locId=' + locationId +
		              '&theme=' + locationType +
		              '&mapsource=' + markerSource +
		              '&query=' + encodeURIComponent(priv.query);

			// Call the url
			GDownloadUrl(url, function(data, responseCode) {
				if (responseCode == 200) {
					// Parse the returned url
					var xmlDoc = GXml.parse(data);
					priv.setMarkers(xmlDoc);
				}
            });
        },

        facetClick: function(href) {
            priv.query = priv.getHashValue(href, 'query');
            Searchmap.updateMap();
        },

		loadGoogleMaps: function(doLoadDimensions, locationIdentifier, mapType, options, markersXml) {
            if (options) {
                $.extend(config, options);
            }

            if (GBrowserIsCompatible()) {
                // set current accommodation id
                if (locationIdentifier != '' && locationIdentifier.split('~')[0] == 'ACC') {
                    priv.currentId = parseInt(locationIdentifier.split('~')[1]);
                }

                // load googlemaps
                priv.googleMap = new GMap2($('#googleMap').get(0));

                // initially set default lat, lng, zoomlevel
                var lat = priv.defaultLat;
                var lng = priv.defaultLng;
                var z = priv.defaultZoom;

                // get previous map state from cookie if available
                var cookieStr = $.cookie(priv.cookiePrefix + "searchmap");
                if (cookieStr != null && cookieStr != '') {
                    var arrValues = cookieStr.split('^');
                    if (arrValues.length == 3) {
                        lat = parseFloat(arrValues[0]);
                        lng = parseFloat(arrValues[1]);
                        z = parseInt(arrValues[2]);
                    }
                }

                if (locationIdentifier != '') {
                    var split = locationIdentifier.split('~');
                    var typeId = split[0];
                    var locId = split[1];
                    $.getJSON(priv.pathPrefix + '/js/ajax/get_locations.ashx?type_id=' + typeId + '&locId=' + locId, function(item) {
						if ((item.GeoInfo.NorthWestLatitude != 0 && item.GeoInfo.NorthWestLatitude != undefined) && (item.GeoInfo.NorthWestLongitude != 0 && item.GeoInfo.NorthWestLongitude != undefined)) {
                            var gllTopLeft = new GLatLng(item.GeoInfo.NorthWestLatitude, item.GeoInfo.NorthWestLongitude);
                            var gllBotRight = new GLatLng(item.GeoInfo.SouthEastLatitude, item.GeoInfo.SouthEastLongitude);
                            var gllbBounds = new GLatLngBounds();
                            gllbBounds.extend(gllTopLeft);
                            gllbBounds.extend(gllBotRight);
                            lat = gllbBounds.getCenter().lat();
                            lng = gllbBounds.getCenter().lng();
                            z = priv.googleMap.getBoundsZoomLevel(gllbBounds);
                        } else {
                            lat = item.GeoInfo.Latitude;
                            lng = item.GeoInfo.Longitude;
                            if (typeId == 'LND') {
                                z = 6;
                            } else if (typeId == 'STR') {
                                z = 8;
                            } else if (typeId == 'PLT') {
                                z = 14;
                            } else if (typeId == 'ACC') {
                                z = 16;
                            }
                        }

						priv.createMap(lat, lng, z, mapType, markersXml);
                    });
                } else {
					priv.createMap(lat, lng, z, mapType, markersXml);
                }
            }
        },

        // Show Google map with the directions for a car traveller.
        // Directions are from Utrecht, NL to the specified accommodation.
        // Standard map is used, viewpoint and zoom auto-adjusted.
        // routeTo: string - Google maps query for destination place. Because using accommodation name
        // usually leads to ambiguous results and no directions, coordinates are used
        showDirections: function(routeTo, options, langCode) {
            if (langCode == '' || langCode == null || langCode == undefined) {
                langCode = 'nl_NL';
            }

            if (!GBrowserIsCompatible()) {
                return;
            }
            if (!routeTo) {
                return;
            }
            priv.routeTo = routeTo;
            if (options) {
                $.extend(config, options);
            }

            // load googlemaps
            priv.googleMap = new GMap2($('#googleMap').get(0));
            priv.googleMap.setCenter(new GLatLng(priv.defaultLat, priv.defaultLat), priv.defaultZoom);
            priv.googleMap.addControl(new GLargeMapControl());
            priv.googleMap.addControl(new GMapTypeControl());
            priv.googleMap.addControl(new GScaleControl());
            priv.googleMap.addControl(new GOverviewMapControl());
            priv.googleMap.enableDoubleClickZoom();

            Searchmap.updateDirections(langCode);
        },

        sendGoogleMapDirections: function(accoId, langCode) {
            if (langCode == '') {
                langCode = 'nl_NL';
            }

            $('#googleDirections').html('');
            priv.googleMap.clearOverlays();

            // set googlemaps directions object
            directionsDiv = document.getElementById('googleDirections');
            directions = new GDirections(priv.googleMap, directionsDiv);

            var ToText = $('#routeToText').val();
            var addr = $('#dirAddress').val();
            var city = $('#dirCity').val();
            var country = $('#dirCountry').val();
            var routeFrom = "";
            if (city != '') {
                routeFrom = addr != '' ? addr + " " : "";
                routeFrom += city + " " + country;
            }
            else {
                routeFrom = Resource.GetText('send_route_from');
            }

            GEvent.addListener(directions, "load", function() {
                // set maptype to map
                priv.googleMap.setMapType(G_NORMAL_MAP);

                // write route without any styling for print and email                
                var route = directions.getRoute(0);
                var start = route.getStartGeocode();
                var end = route.getEndGeocode()
                var container = document.getElementById("RouteSimplified");
                var simple = String.format(Resource.GetText('send_route_beginendpoint'), start.address, end.address, directions.getSummaryHtml());
                for (i = 0; i < route.getNumSteps(); i++) {
                    simple += (i + 1) + ". " + route.getStep(i).getDescriptionHtml() + " " + route.getStep(i).getDistance().html + " (" + route.getStep(i).getDuration().html + ")<br/><br/>";
                }
                simple += Resource.GetText('send_route_description');
                container.value = simple;

                formsubmit.sendRoute(accoId);
            });

            GEvent.addListener(directions, "error", function() {
                var errorDiv = document.getElementById("route-error");
                var addressPanel = document.getElementById("phRouteToAddress");
                var toolsPanel = document.getElementById("divTools");
                err = directions.getStatus();
                if (err.code == 603 || err.code == 604) // no route or address due to legal reasons/lacking data
                {
                    errorDiv.innerHTML = String.format(Resource.GetText('send_route_error_noroute'), routeFrom, ToText);
                    addressPanel.style.display = "none";
                    toolsPanel.style.display = "none";
                }
                else if (err.code == 601 ||  //missing query
                    err.code == 602 ||  //unknown address 
                    err.code == 400 ||  //bad request
                    err.code == 500)   //server error
                {
                    errorDiv.innerHTML = String.format(Resource.GetText('send_route_error_address'), routeFrom, ToText);
                }
                else if (err.code == 620)   //limit nr of queries allowed exceeded
                {
                    errorDiv.innerHTML = Resource.GetText('send_route_error_tryagain');
                    addressPanel.style.display = "none";
                    toolsPanel.style.display = "none";
                }
                else {
                    errorDiv.innerHTML = Resource.GetText('send_route_error');
                    addressPanel.style.display = "none";
                    toolsPanel.style.display = "none";
                }

            });
            directions.load("from: " + routeFrom + " to: " + priv.routeTo, { "locale": langCode });
        },

        // Update car traveler directions with the new start address.
        updateDirections: function(langCode) {
            if (langCode == '') {
                langCode = 'nl_NL';
            }

            if (!GBrowserIsCompatible()) {
                return;
            }
            var $directionsContainer = $('#googleDirections').html('');
            var $errorContainer = $("#route-error").hide();
            var toolsPanel = $("divTools");
            priv.googleMap.clearOverlays();
            var directions = new GDirections(priv.googleMap, $directionsContainer.get(0), { travelMode: 1 });

            var addr = $('#dirAddress').val();
            var city = $('#dirCity').val();
            var country = $('#dirCountry').val();
            var routeFrom = country;
            if (city != '') {
                routeFrom = addr + " " + city + " " + routeFrom;
            }
            var query = "from: " + routeFrom + " to: " + priv.routeTo;
            GEvent.addListener(directions, "error", function() {
                var err = directions.getStatus();
                if (err.code == 603 || err.code == 604) // no route or address due to legal reasons/lacking data
                {
                    $errorContainer.html(strErrorCodeTextInvalidData);
                }
                else if (err.code == 601 ||  //missing query
                    err.code == 602 ||  //unknown address 
                    err.code == 400 ||  //bad request
                    err.code == 500)   //server error
                {
                    $errorContainer.html(strErrorCodeTextInvalidInputData);
                }
                else if (err.code == 620)   //limit nr of queries allowed exceeded
                {
                    $errorContainer.html(strErrorCodeTextLimitQueryExceeded);
                }
                else {
                    $errorContainer.html(strErrorCodeTextUnhandled);
                }
                $errorContainer.show();
                toolsPanel.show();
            });
            directions.load(query, { "locale": langCode });
        }
    };
} (jQuery);

$(document).unload( function () { GUnload(); } );
