﻿/**
 * @author Baris Bikmaz namics.ag
 * @requires jquery 1.3.2 and Actions.js
 */

var MAPS = {
	googleMapDivId: "GoogleMap",
	map: null,
	zoomLimit: 15,
	iconUrl: "http://" + window.location.host + "/_layouts/images/Migros.SP.MKS.Frontend/googleMaps/marker",
	gdir: null,
	gmarkers: [],
	htmls: [],
	nbrOfMarkers : 0,
	createdMarkers : 0,
	to_htmls: [],
	version: "2.0",
	from_htmls: [],
	bounds : new GLatLngBounds(),
	curMarker: null,
	markerGroups: { "type1": [], "type2": [] },
	reasons: [],
	lang: {
			direction: "Route berechnen",
			toHere: "Nach hier",
			fromHere: "Von hier",
			bttDirection: "Los!",
			startAddr: "Startadresse",
			endAddr: "Zieladresse",
			back: "zurück"
	}
};

/**
 * Initialize the map and load all events for the site
 */
MAPS.initializeMap = function() {
	// reset CSS-Styles if JavaScript is enabled
	$(".slider").slideUp("fast");
	// set the check in the checkbox after reload
	$(".filterBox input").attr("checked", "checked");

	// Create the map	
	if (MAPS.createMap(MAPS.googleMapDivId) === null){ return; }
	
	var error = false;    
	if (typeof data === "undefined") {
		Utils.log("error", "(MAPS.initializeMap) => Global data object for markers not found or incorrect format. Check the lat long values.");
		error = true;
	}
	
	
	// START MARKER SETUP
	if (!error) {
		//count the marker
		for (var x in data.MARKER) {
			MAPS.nbrOfMarkers++;
		}

		// insert the marker into the map
		for (x in data.MARKER) {
			var lat = data.MARKER[x].lat;
			var lng = data.MARKER[x].long;
			var letter = data.MARKER[x].letter;
			var marker = null;
			Utils.log("log", "(MAPS.initializeMap) => " + letter +".) lat:" + lat + ", long:" + lng);
			
			MAPS.createdMarkers++;
			// Validate lat & long
			var regEx = /^\d{1,2}\.\d+$/;
			if ( ( regEx.test(lat) === false ) || ( regEx.test(lng) === false) ) {
				//if no valid lat, long try geocoding by address
				Utils.log("info", "(MAPS.initializeMap) => Marker contains no or invalid latitude and longitude value");
				MAPS.findLocation(data.MARKER[x], true);
			}
			else{
				lat = parseFloat(lat);
				lng = parseFloat(lng);
				marker = MAPS.createMarker(data.MARKER[x]);
				// add marker to the map
				MAPS.map.addOverlay(marker);
			}
		}
	}


}; // end initialize map


/**
 * Sets the language specific variables used by other functions
 */
MAPS.setLangugeVariables = function() {

	if (typeof data == "undefined") {
		Utils.log("error", "GoogleMaps => No data found");
		return false;
	}
	
	if (typeof data.LANG == "undefined") {
		Utils.log("error", "GoogleMaps => No language entries found");
		return false;
	}

	//Google failure codes
	try {
		MAPS.reasons[G_GEO_SUCCESS] = data.LANG.G_GEO_SUCCESS;
		MAPS.reasons[G_GEO_MISSING_ADDRESS] = data.LANG.G_GEO_MISSING_ADDRESS;
		MAPS.reasons[G_GEO_UNKNOWN_ADDRESS] = data.LANG.G_GEO_UNKNOWN_ADDRESS;
		MAPS.reasons[G_GEO_UNAVAILABLE_ADDRESS] = data.LANG.G_GEO_UNAVAILABLE_ADDRESS;
		MAPS.reasons[G_GEO_BAD_KEY] = data.LANG.G_GEO_BAD_KEY;
		MAPS.reasons[G_GEO_TOO_MANY_QUERIES] = data.LANG.G_GEO_TOO_MANY_QUERIES;
		MAPS.reasons[G_GEO_SERVER_ERROR] = data.LANG.G_GEO_SERVER_ERROR;
		MAPS.reasons[G_GEO_BAD_REQUEST] = data.LANG.G_GEO_BAD_REQUEST;
		MAPS.reasons[G_GEO_MISSING_QUERY] = data.LANG.G_GEO_MISSING_QUERY;
		MAPS.reasons[G_GEO_UNKNOWN_DIRECTIONS] = data.LANG.G_GEO_UNKNOWN_DIRECTIONS;
	}
	catch (err) {
		Utils.log("error", "GoogleMaps => ENtries for Geocode errors not found.");
	}


	MAPS.lang.Direction = data.LANG.direction;
	MAPS.lang.ToHere = data.LANG.toHere;
	MAPS.lang.FromHere = data.LANG.fromHere;
	MAPS.lang.BttDirection = data.LANG.bttDirection;
	MAPS.lang.StartAddr = data.LANG.startAddr;
	MAPS.lang.EndAddr = data.LANG.endAddr;
	MAPS.lang.Back = data.LANG.back;
};

/**
 * Returns the html of a marker
 * @param {object} markerX JSON Definition of a marker 
 */
MAPS.getMarkerHTML = function(markerX) {
    return '<div class="mapContent">' + 
		'<h3>' + markerX.title + '</h3>' +
		'  <p>' + markerX.street + '</p>' + 
		'  <p class="location">' + markerX.zip + ' ' + markerX.location + '</p>' +
		'</div>';
};


/**
 * Creates the google map
 * @param {string} mapId id of the google map div
 */
MAPS.createMap = function(mapId) {
	Utils.log("info", "(MAPS.createMap) => start to create google map");
	try {
		if (!GBrowserIsCompatible() || (document.getElementById(mapId) === null)) {
			Utils.log("error", "(MAPS.createMap) => Google Map div with id '" + mapId + "' not found!");
			return null;
		}
	}
	catch (err) {
		Utils.log("error", "(MAPS.createMap) => Error in createMap: " + err);
		return null;
	}
	
	var map = new GMap2(document.getElementById(mapId));
	map.setCenter(new GLatLng(0, 0), 0, G_NORMAL_MAP);
	map.addControl(new GSmallMapControl());
	map.addControl(new GMapTypeControl());
	MAPS.map = map;
	Utils.log("info", "(MAPS.createMap)=> Map successfully created. Now Setting laguage variables");
	MAPS.setLangugeVariables();

	// Set center to switzerland
	var switzerland = new GLatLng(46.717269, 8.481445);
	MAPS.map.setCenter(switzerland, 7);
	
	/**
	 * Event Bindings for the map
	 */
	$(".filterBox input").click(function() {			
			var status = $(this).attr("checked").toString();
			var migrosType = $(this).val();
			MAPS.toggleMarkers(status, migrosType);
	});

	if ($(".locationOverview").length > 0) {
			var googlemapObj = $("#" + MAPS.googleMapDivId);

			$(window).scroll(function() {
					var startPos = 270;
					var moveMap = typeof window.pageYOffset != 'undefined' ? window.pageYOffset : document.documentElement &&
					document.documentElement.scrollTop ?
					document.documentElement.scrollTop : document.body.scrollTop ?
					document.body.scrollTop : 0;

					if (moveMap > startPos) {				
							googlemapObj.css("margin-top", parseInt(moveMap - startPos, 10) + "px");
					}
			});
	}
		
	return map;
};

/**
 * This function create the marker
 * @param {array} markerX 
 * JSON Definition of a marker
 */
MAPS.createMarker = function(markerX) {	
	var cat = markerX.category;
	var locId = markerX.id;
	var lat = markerX.lat;
	var lng = markerX.long;
	var point = new GLatLng(lat, lng);
	var html = MAPS.getMarkerHTML(markerX);
	var letter = markerX.letter;
	var myIcon = new GIcon(G_DEFAULT_ICON);	

	myIcon.image = (cat == 2) ? MAPS.iconUrl + "/blue" + letter + ".png" : myIcon.image = MAPS.iconUrl + "/red" + letter + ".png";	
	Utils.log("log", "(MAPS.createMarker ) => Marker image: " + myIcon.image);

	var marker = new GMarker(point, { icon: myIcon });
	MAPS.setCurMarker(locId);
	MAPS.to_htmls[locId] = html;
	
	GEvent.addListener(marker, "mouseover", function() {
		marker.openInfoWindowHtml(html);
	});

	// add the marker to the group
	MAPS.markerGroups["type" + cat].push(marker);

	// save the info we need to use later for the side_bar
	MAPS.gmarkers[locId] = marker;
	MAPS.htmls[locId] = html;

	MAPS.extendMap(point);
	return marker;
};

/**
 * Extends the map, so that all markes can be viewed
 * @param {GPoint}  Point of the marker
 */
MAPS.extendMap = function (point) {
	MAPS.bounds.extend(point);
	Utils.log("log","MAPS.createdMarkers:" + MAPS.createdMarkers + " - MAPS.nbrOfMarkers:" + MAPS.nbrOfMarkers );
	if (MAPS.nbrOfMarkers !== 0 && MAPS.createdMarkers != MAPS.nbrOfMarkers) {return false;}
	var zoomLvl = ( MAPS.nbrOfMarkers == 1 || MAPS.nbrOfMarkers == 0 ) ? 18 : MAPS.map.getBoundsZoomLevel(MAPS.bounds);
	MAPS.map.setCenter(MAPS.bounds.getCenter(), zoomLvl);
};

/**
 * This functions show/hide markers
 * @param {boolean} st status of the clicked checkbox isChecked
 * @param {string} mT migrosType (business, sport,...)
 */
MAPS.toggleMarkers = function(st, mT) {
	var currentGroup = MAPS.markerGroups["type" + mT];
	var l = currentGroup.length;

	if (st == "false") {
		MAPS.map.closeInfoWindow();
		for (i = 0; i < l; i++) {
			currentGroup[i].hide();
		}
		$("div.cat" + mT).fadeOut("normal");
	}
	else {
		for (i = 0; i < l; i++) {
			currentGroup[i].show();
			$("div.cat" + mT).fadeIn("normal");
		}
	}
};

/**
 * Calls the geocoder method
 * @param {array} globalData		marker hash, that contains the name for street, country and so on..
 * @param {bool} isSingleItem		true is only a single item is in globaldata
 */
MAPS.findLocation = function(globalData, isSingleItem) {
	if (typeof globalData == "undefined") {
		Utils.log("error", "(findLocation)=> globalData not found.");
		return false;
	}
		
	isSingleItem =  isSingleItem || false;

    // Get the one marker from global data
	var theMarker = null;
	
	Utils.log("dir", globalData);
	
	if ( isSingleItem ) {
		theMarker = globalData;		
	}
	else { 		
		for (var x in globalData.MARKER) {
			theMarker = globalData.MARKER[x];
			break;
		}
		
		if (theMarker === null) {
			Utils.log("error", "(MAPS.findLocation)=> no marker found.");
			return false;
		}
	}

	// Check if coordinates have the correct format
	var regEx = /^\d{1,2}\.\d+$/;
	var blnLatLongExists = true;
	if ((regEx.test(theMarker.lat) === false) || (regEx.test(theMarker.long) === false)) {
		Utils.log("info", "(MAPS.findLocation) => Try to geocode by address.");
		blnLatLongExists = false;
	}
				
	if (blnLatLongExists) {        
		// GEOCODING BY COORDINATES
		Utils.log("info", "(MAPS.findLocation)=> Lat, long found, now creating marker.");
		MAPS.addSingleMarkerToMap(theMarker);
	}
	else {
		//GEOCODING BY ADDRESS
		if (typeof theMarker.street === "undefined" || typeof theMarker.location === "undefined") {
				Utils.log("error", "(MAPS.findLocation)=> data contains invalid data.");
				return false;
		}
		
		var streetParts  = theMarker.street.split(",");  // Fitnesspart, Buchenstrasse 5
		var street  = streetParts[streetParts.length-1]; // Buchenstrasse 5
		
		var address = street + "," + theMarker.zip +" "+theMarker.location;
		Utils.log("info", "(MAPS.findLocation)=> geocoding address: " + address);	
		MAPS.geoCode(address, theMarker, true);
	}
	
	return theMarker;
};

/**
 * Geocodes an address. If the address not found, the method tries to 
 * geocode the region.
 *
 * @param {string} address 
 *			The adress to geocode
 * @param {object} marker
 *      marker hash, that contains the name for street, country and so on..
 * @param {boolean} blnTryRegion 
 *			If true the method will try to geocode by region if normal address fails.
 * @return {GMARKER} the inserted marker or null
 */
MAPS.geoCode = function(address, marker, blnTryRegion){
	
	blnTryRegion = blnTryRegion || false;
	var geocoder = new GClientGeocoder();
	
	geocoder.getLocations(address, function(response) {
			//MAPS.map.clearOverlays();
			var blnFailure = response && response.Status.code != 200;
			if (blnFailure && blnTryRegion) 
			{				
				var newAddress = marker.zip +" "+marker.location + ", Schweiz";
				Utils.log("info", "(MAPS.geoCode)=>Address not found. Try to geocode region: " + newAddress );
				MAPS.geoCode(newAddress, marker, false);
			}
			else if(blnFailure)
			{
				Utils.log("error", "MAPS.geoCode)=>Unable to locate " + decodeURIComponent(response.name));				
				return null;
			}
			else 
			{               
				var place = response.Placemark[0];

				marker.lat = place.Point.coordinates[1];
				marker.long = place.Point.coordinates[0];

				Utils.log("info", "(MAPS.geoCode)=> Address found, lat:" + marker.lat +", lng:" + marker.long);			
				MAPS.addSingleMarkerToMap(marker);						
			}
	});
};

/**
 * Adds a single marker into the Google Map
 *
 * @param {object} markerX
 *      marker hash, that contains the name for street, country and so on..
 * @return {GMARKER} the inserted marker or null
 */
MAPS.addSingleMarkerToMap = function(markerX) {
	// Checks
	if (typeof markerX == "undefined") {
		Utils.log("error", "(MAPS.addSingleMarker) => marker is not defined.");
		return null;
	}
	
	var gMarker = MAPS.createMarker(markerX);
	MAPS.map.addOverlay(gMarker);
	var point = new GLatLng(markerX.lat, markerX.long);
	
	MAPS.extendMap(point);
			
	return gMarker;
};

/**
 * This function set the current Marker Id
 * @param {int} markerId Id of Marker
 */
MAPS.setCurMarker = function(markerId) {
	MAPS.curMarker = markerId;
};

/**
 * This function return the current Marker Id
 * @return {int} curMarker Id of current Marker
 */
MAPS.getCurMarker = function() {
	return MAPS.curMarker;
};

/**
 * This function reset the Zoomlevel if it's too height
 * @return {int} newZoomLevel zoomLevel for the current map-part
 */
MAPS.limitZoom = function(curZoomLevel) {
	var newZoomlevel = 0;
	if (curZoomLevel > MAPS.zoomLimit) {
		newZoomlevel = MAPS.zoomLimit;
	}
	else {
		newZoomlevel = curZoomLevel;
	}
	return newZoomlevel;
};


/**
 * This function picks up the click and opens the corresponding info window
 * @param {int} i Beschreibung
 */
MAPS.myclick = function(i) {
	MAPS.gmarkers[i].openInfoWindowHtml(MAPS.htmls[i]);
};

