
var _map 			= null;
var _listCanvas		= null;		// list to show markertext
var _header			= null;		// currently not in use ! 

var _markerManager 	= null;		 
var _bounds 		= null;		 
var _markers 		= new Array();		// all marker array
var _drawedMarkers 	= null;		// current viewport marker.id array

var _activeListElement = null;	// active element ID
var _closeEventHandle  = null;	// infoWindow CloseEvent

var _hasZoomed		  = false;

var _activeMarker	   = null;	// currently not in use !
var _highlightedMarker = null;	// currently not in use !
var _highlightIcon	   = null;	// currently not in use !

var _pagingBackLink	   = null;
var _pagingNextLink	   = null;
var _numberOfPages 	   = null;  
var _activePage 	   = null;
var _isLocalized       = null;
var _visibleMarkerCount= 0;

var _tx_googlemaps_LL = null;
		

/**
 * Returns the current IE version number or -1, if no IE is detected
 * 
 * @return int ie version or -1 
 */
function vIE(){
	return (navigator.appName=='Microsoft Internet Explorer')?parseFloat((new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})")).exec(navigator.userAgent)[1]):-1;
}

/**
 * Entity representing a geographic location.
 * 
 * @param lat Latiude
 * @param lng Longitude
 */
function tx_jo_googlemaps_GeoPoint(lat, lng) {
	  this.lat = lat;
	  this.lng = lng;
}

/**
 * Marker entity to encapsulate all data related to a marker, that will be rendered by this map.
 * 
 * @param gMarker Google Maps marker object.
 * @param tx_jo_googlemaps_GeoPoint point
 * @param String name
 * @param String listText
 * @param String infoWindowText
 */
function tx_jo_googlemaps_Marker(gMarker, point, name, listText, infoWindowText, listText_detail){
	this.gMarker    		= gMarker;			
	this.point	    		= point;					// lat lang
	this.name 	    		= name;						// mouseOver
	this.listText   		= listText;					// html for list
	this.listText_detail   	= listText_detail;					// html for list
	this.infoWindowText 	= infoWindowText;		// html for infoWindow	
}

/**
 * 
 * @param gmap
 * @param list_Canvas
 * @param header
 * @param jsonData
 * @param llJsonData JSON object with several LL-attributes, to enable usage of LL.
 * @return
 */
function tx_jo_googlemaps_initialize(gmap, list_Canvas, header, jsonData, llJsonData){
//	console.log('tx_jo_googlemaps_initialize');
	this._listCanvas			= list_Canvas;
	this._map 					= gmap;
	this._header 				= header;
	
    _map.setUIToDefault();   

	_highlightIcon 		= new GIcon(G_DEFAULT_ICON);
	if(vIE()!=6) _highlightIcon.image = "../typo3conf/ext/jo/res/css/img/gMaps_marker_active.png";
	else _highlightIcon.image = location.protocol+"//"+location.host+"/typo3conf/ext/jo/res/css/img/gMaps_marker_active.png";

	_bounds = new GLatLngBounds();
	
	// localization logic, reduce shown markers
	_isLocalized = isLocalized();
	
	// save LL data in locale var
	_tx_googlemaps_LL = llJsonData;
	
	var filteredJsonData = filterItemsByLocalization(jsonData);
	
	if(filteredJsonData.length == 0)
	{
		// show all results to avoid that nothing is shown
		filteredJsonData = jsonData;
				
		if(_isLocalized)
		{
			// show an error message
			$('#error-3').show();
		}
	}
	
	tx_jo_googlemaps_generateMarkers(filteredJsonData);			// Create Marker array
	var itemsPerPage = 10;
		
	if(filteredJsonData.length == 1)
	{		
		var listHTML='';
		var visibility = '';
		
		// console.log(filteredJsonData);
		var subItems = tx_jo_googlemaps_getSubItems(filteredJsonData,0,1);
		
		listHTML += subItems[0]['list'].list_text_exactlyone;
						
		$("div.ce-gmap div.map-list").html(listHTML);
		
	} else if(filteredJsonData.length > 1){		
		// more than 1 items found render the list with normal items
		
		var listHTML='';
		var itemsHTML='';
		var visibility = '';
		
		// create pages of items
		this._numberOfPages = Math.ceil(filteredJsonData.length / itemsPerPage);
		
		for(var i=0; i < this._numberOfPages; i++)
		{
			// 	create ul with page as class attribute
			itemsHTML = '';			
			var subItems = tx_jo_googlemaps_getSubItems(filteredJsonData,(i*itemsPerPage),itemsPerPage);			
			for(var j = 0; j < subItems.length; j++)
			{			
				itemsHTML += '<li>' + subItems[j]['list'].list_text + '</li>';
			}			
			if(i > 0)
				visibility = ' style="display:none;" ';			
			listHTML += '<ul class="pages page-' + i +'"'+visibility+'>' + itemsHTML + '</ul>';						
		}
				
		//console.log(listHTML);
		
		$("div.ce-gmap div.map-list").html(listHTML);
		
		// initialize paging only if there are more than one pages
		if(this._numberOfPages > 1)
		{
			this._pagingBackLink = $("#top-paging #map-link-previous").html();
			this._pagingNextLink = $("#top-paging #map-link-next").html();
			this._activePage = 1;
			$('.paging').html(tx_jo_googlemaps_getMarkupForPaging());			
		}	
			
	}	
	
	// map rendering
	_drawedMarkers = new Array(0);
		
	var zoomToFit =  _map.getBoundsZoomLevel(_bounds);
	_map.setCenter(_bounds.getCenter(),zoomToFit);  
	
	_markerManager = new MarkerManager(_map);
	
	tx_jo_googlemaps_refreshViewport();		// show markers in viewport

	GEvent.addListener(_map, "zoomend", function(oldZoom, newZoom){
		if (_activeListElement != null){
			_hasZoomed = true;
			tx_jo_googlemaps_refreshInfoWindow(_activeListElement);
			_hasZoomed = false;
		}
	});
	
	GEvent.addListener(_map, "moveend", function(){
		tx_jo_googlemaps_refreshViewport();
	});	
		
	tx_jo_googlemaps_setCenter();
}


function tx_jo_googlemaps_getSubItems(data, offset, count)
{
	if(offset > data.length-1)
	{
		return false;
	}
	if(data.length-offset < count)
	{
		count = data.length-offset;
	}		
	// alert("Offset: " + offset);
	// alert("Count: " + count);
	var subItemsArr = new Array(count);
	var index = 0;	
	for(var k=offset; k < (offset+count); k++)
	{
		subItemsArr[index] = data[k];
		index++;
	}
	return subItemsArr;
	
}

function tx_jo_googlemaps_getMarkupForPaging()
{			
	var markup = '';	
	if(this._activePage > 1) 
		markup += this._pagingBackLink;	
	for(var i=1; i <= this._numberOfPages; i++)
	{
		if(i==this._activePage)
		{
			markup += '<span class="current">'+ i +'</span>';
		}else 
		{
			markup += '<a onclick="tx_jo_googlemaps_navPage('+ i +');return false;" class="navtopage" href="#">'+ i +'</a>';
		}
	}
	if(this._activePage != this._numberOfPages) 
		markup += this._pagingNextLink;
	return markup;
}


function tx_jo_googlemaps_navPage(index)
{
	this._activePage = index;
	$("ul.pages").hide();	
	$("ul.page-" + (index-1)).show();
	$(".paging").html(tx_jo_googlemaps_getMarkupForPaging());
}

function tx_jo_googlemaps_navNext()
{
	var index = this._activePage;		
	$("ul.pages").hide();	
	$("ul.page-" + index).show();
	this._activePage++;
	$(".paging").html(tx_jo_googlemaps_getMarkupForPaging());
}

function tx_jo_googlemaps_navBack()
{
	var index = this._activePage-2;		
	$("ul.pages").hide();
	$("ul.page-" + index).show();
	this._activePage--;
	$(".paging").html(tx_jo_googlemaps_getMarkupForPaging());
}


function tx_jo_googlemaps_switchGoogleMap(viewmode)
{
	switch(viewmode)
	{
		case 'list' : 
			
			$("div.ce-gmap .map-box").hide();
			$("div.ce-gmap .map-list").show();
			$("div.ce-gmap a#goolemap-link-map").removeClass("current");
			$("div.ce-gmap a#goolemap-link-list").addClass("current");
			$("a#map-all-link").hide();
			
			if(this._numberOfPages > 1)
				$(".paging").show();
			
			tx_jo_googlemaps_refreshHeader('list');
			
			break;
		case 'map' :
			$("div.ce-gmap div.header-selection").show();
			tx_jo_googlemaps_refreshHeader();
			
			$("div.ce-gmap .map-box").show();
			$("div.ce-gmap .map-list").hide();
			$("div.ce-gmap a#goolemap-link-map").addClass("current");
			$("div.ce-gmap a#goolemap-link-list").removeClass("current");
			$(".paging").hide();
			break;
	}
}

function tx_jo_googlemaps_refreshViewport(){
	var bounds 	  = _map.getBounds();
	
	var southwest = bounds.getSouthWest();
	var swLat = southwest.lat();
	var swLng = southwest.lng();
	 		
	var northeast = bounds.getNorthEast();
	var neLat = northeast.lat();
	var neLng = northeast.lng();

	var drawMarkers 	= new Array();		//Int Array (index der Marker zum Vergleich)
	var removeMarkers 	= new Array();
			
	_visibleMarkerCount = 0;	
	var lastMarkerDrawed = 0;
	for (var i=0; i<_markers.length; i++){
				
    	var markerLat	= _markers[i].point.lat;
    	var markerLng	= _markers[i].point.lng;
    	var isDrawed 	= tx_jo_googlemaps_containsInt(i,_drawedMarkers);
    	   	
    	if ((markerLat > swLat) && (markerLng > swLng) && (markerLat < neLat) && (markerLng < neLng)){
    		_visibleMarkerCount++;
    		lastMarkerDrawed = i;
    		if (isDrawed){        		
            }else {
				drawMarkers.push(i);
            }
    	}else{
        	if (isDrawed){
				removeMarkers.push(i);
        	}
    	}
	}
		
	tx_jo_googlemaps_refreshMarkerManager (drawMarkers,removeMarkers);
	tx_jo_googlemaps_refreshTextBox		 (drawMarkers,removeMarkers);
	tx_jo_googlemaps_refreshDrawedMarkers (drawMarkers,removeMarkers);
	tx_jo_googlemaps_refreshHeader();
	
	$("#map-all-link").hide();
	$('div#facility-detail').hide();
		
	if(_visibleMarkerCount == 1)
	{
		tx_jo_googlemaps_createMarkerTextBoxById_detailed(lastMarkerDrawed);		
	}
}


/**
 * Refresh the MarkerManager - add new visible Markers and remove not visible Markers
 * 
 * @param draw	markerIDs to draw
 * @param remove markerIDs to remove
 */
function tx_jo_googlemaps_refreshMarkerManager(draw,remove){
	var tempArray = new Array(draw.length);
	var tempMarker = null;
	     	
	for (var i=0; i<draw.length; i++){
    	tempMarker = _markers[draw[i]];
    	tempArray[i] = tempMarker.gMarker;
	}

	// refresh markerManager
	_markerManager.addMarkers(tempArray,1);						// add new visible markers 
	for (var i=0; i<remove.length; i++){						// remove all not visible markers (removeMarker Array)
		tempMarker = _markers[remove[i]];
		_markerManager.removeMarker(tempMarker.gMarker);
	}
	
	_markerManager.refresh();
}

/**
 * Refresh marker listview - add new and remove not visible
 * 
 * @param draw	markerIDs to draw
 * @param remove markerIDs to remove
 */	
function tx_jo_googlemaps_refreshTextBox(draw,remove){
	// remove
	for (var i=0; i<remove.length; i++){
		tx_jo_googlemaps_removeElementById(remove[i]);
	}
		
	// add
	_listCanvas.show();
	for (var i=0; i<draw.length; i++){
		tx_jo_googlemaps_createMarkerTextBoxById(draw[i]);
	}		
}

/**
 * Refresh drawedMarker array
 *
 * @param draw	markerIDs to draw
 * @param remove markerIDs to remove
 */	
function tx_jo_googlemaps_refreshDrawedMarkers(draw,remove){	
//	console.log('tx_jo_googlemaps_refreshDrawedMarkers');
	for (var i=0; i<remove.length; i++){
		var j = 0;
    	var isNotFound = true;
    	while (isNotFound && j<_drawedMarkers.length){
    		if (_drawedMarkers[j] == remove[i]){
    			_drawedMarkers.splice(j,1);
            	isNotFound = false;
    		}
    		j++;
    	}
	}

	for(var i=0; i<draw.length; i++){
		_drawedMarkers.push(draw[i]);
	}
	
	// if no marker is visible add errorbox
	if (_drawedMarkers.length == 0){
		tx_jo_googlemaps_createErrorBox();
	}else{
		tx_jo_googlemaps_removeErrorBox();
	}
}

/**
 * Überprüft ob x im Array enthalten ist
 */	
function tx_jo_googlemaps_containsInt (x, array){
	for (var i=0; i<array.length; i++){
		if (array[i] == x){
			return true;
		}
	}
	return false;
}

function tx_jo_googlemaps_generateMarkers(data) {
	var markerCount = 0;
	$.each(data, function(i,dataObj){
		markerCount = parseInt(i)+1;
	});
	
	$.each(data, function(i,dataObj){
		
		var name 	= "marker "+dataObj.uid;
		var point = new tx_jo_googlemaps_GeoPoint(dataObj.map.point.latitude, dataObj.map.point.longitude);
		var infoWindowText = dataObj.map.balloon;
				
		var listText = dataObj.map.list_text;		
		var listText_detail = dataObj.map.list_text_exactlyone;	
		var title = dataObj.list.title;
				
		// localization active
		if(_isLocalized)
		{
			// delete morelink from the balloon and show info link instead
			var partsArr = infoWindowText.split("###MORELINK###");
			infoWindowText = partsArr[0] + partsArr[2];
			if(markerCount > 1)
			{	
				infoWindowText = infoWindowText.replace(/###INFOLINK###/g,'',infoWindowText);
				infoWindowText = infoWindowText.replace(/###ID###/g,i,infoWindowText);
			} else 
			{			
				partsArr = infoWindowText.split("###INFOLINK###");
				infoWindowText = partsArr[0] + partsArr[2];							
			}
		} else
		{
			var partsArr = infoWindowText.split("###INFOLINK###");
			infoWindowText = partsArr[0] + partsArr[2];
			infoWindowText = infoWindowText.replace(/###MORELINK###/g,'',infoWindowText);
		}		
				
		var gMarker = tx_jo_googlemaps_createGMarker(point, title, infoWindowText);
		_markers[i] 	= new tx_jo_googlemaps_Marker(gMarker, point, title, listText, infoWindowText, listText_detail);
		
	});
	
}

/**
 * Create GMarker
 * 
 * @param tx_jo_googlemaps_GeoPoint point
 * @param String name
 * 
 * @return GMarker	
 */
function tx_jo_googlemaps_createGMarker (point,name){
	var icon	= new GIcon(G_DEFAULT_ICON);
	if(vIE()!=6) icon.image 	= "../typo3conf/ext/jo/res/css/img/gMaps_marker.png";
	else icon.image 	= location.protocol+"//"+location.host+"/typo3conf/ext/jo/res/css/img/gMaps_marker.png";
	
	var gPoint 	  = new GLatLng(point.lat, point.lng);
			
	var newMarker = new GMarker(gPoint,{title:name,icon:icon});
		
	_bounds.extend (gPoint);
	
	var markerTitle = newMarker.getTitle();
	
	GEvent.addListener(newMarker, "click", function() {
			for (var x=0; x<_markers.length; x++){
			if (markerTitle == _markers[x].name){
				tx_jo_googlemaps_markerClicked(x);
			}
		}
	});
	
	return newMarker;
}
	
// MouseEvents
function tx_jo_googlemaps_highlight(id){
    var marker = _markers[id];
    if(marker) {
    	var name 	= marker.name;
    	var point 	= new GLatLng(marker.point.lat, marker.point.lng);
    	_highlightedMarker = new GMarker(point,{title:name,icon:_highlightIcon});
    	   	    	
     	_map.addOverlay(_highlightedMarker);
    	_activeMarker = marker;
    	_activeMarker.gMarker.hide();
//		_markerManager.removeMarker(marker.gMarker);
//		_markerManager.refresh();
    }
}
function tx_jo_googlemaps_unhighlight(id){
	if(_highlightedMarker){
		_map.removeOverlay(_highlightedMarker);
		_highlightedMarker = null;
	}
	if(_activeMarker){
//		_markerManager.addMarker(_activeMarker.gMarker,1);
//		_markerManager.refresh();
		_activeMarker.gMarker.show();
		_activeMarker = null;
	}
}

/**
 * Add Class 'current' to listElement- show InfoWindow - scroll to current list element
 * 
 * @param int id	markerId
 */
function tx_jo_googlemaps_markerClicked(id){	
	// mark active marker	
	_listCanvas.find("li").removeClass("current");		
	_listCanvas.find('#'+id).addClass("current");

	tx_jo_googlemaps_refreshInfoWindow(id);
	
	if((_listCanvas).attr('display')!='none')
		_listCanvas.scrollTo( '#'+id );
}

/**
 * open or close InfoWindow
 * 
 * @param int id markerID
 */
function tx_jo_googlemaps_refreshInfoWindow(id){
	// open ballon
	var marker = _markers[id];
	var point = new GLatLng(marker.point.lat, marker.point.lng);		//infoWindow geoCoordinate
	
	var gpoint = _map.fromLatLngToContainerPixel(point);				// geoCoordinate to pixel value
	gpoint.y = gpoint.y - 20;											
	point = _map.fromContainerPixelToLatLng(gpoint);					// pixel value to geoCoordinate

	_map.openInfoWindowHtml(point,marker.infoWindowText);
		
	if(_hasZoomed == true){
		GEvent.removeListener(_closeEventHandle);
	}
	
	// close ballon
	_closeEventHandle = GEvent.addListener(_map, "infowindowclose", function(){
		if(_hasZoomed == false){			// don't close window when user zoomed
			tx_jo_googlemaps_closeActiveMarker();
		}
	});
}

/**
 * remove class 'current' form list element
 */
function tx_jo_googlemaps_closeActiveMarker(){
	_listCanvas.find('#'+_activeListElement).removeClass("current");
	_activeListElement = null;
	GEvent.removeListener(_closeEventHandle);
}
      

/**
 * Create list element
 * 
 * @param int id markerID
 */
function tx_jo_googlemaps_createMarkerTextBoxById(id){
	var name  = _markers[id].name; 	
	var text = _markers[id].listText;

	var element = jQuery('<li/>').html(text);
	var eleId 	= id;
	element.attr("id",eleId);    	
	_listCanvas.append(element);
	
	var newElement = _listCanvas.find("li").filter("#"+eleId);
	
	// add eventlistener
	newElement.click(function(){
		tx_jo_googlemaps_markerClicked(this.id);
	});

	newElement.mouseout(function(){
		tx_jo_googlemaps_unhighlight(this.id);
	});

	newElement.mouseover(function(){
		tx_jo_googlemaps_highlight(this.id);
	});
}

function tx_jo_googlemaps_showAllMarkers()
{
	if(_markers.length > 1)
	{
		$("div#facility-detail").hide();
		_listCanvas.show();		
		
		var zoomToFit =  _map.getBoundsZoomLevel(_bounds);
		if(zoomToFit > 1)
		{
			// so every marker will be visible in the middle of the map
			zoomToFit = zoomToFit - 1;
		}	
		_map.setCenter(_bounds.getCenter(),zoomToFit); 
		tx_jo_googlemaps_refreshViewport();	
		_map.closeInfoWindow()
	}	
	
}


function tx_jo_googlemaps_showInfo_detailed(id)
{	
	var marker = _markers[id];
	_map.setCenter(marker.gMarker.getLatLng(),15);	
	tx_jo_googlemaps_createMarkerTextBoxById_detailed(id);
}


/**
 * Create list element
 * 
 * @param int id markerID
 */
function tx_jo_googlemaps_createMarkerTextBoxById_detailed(id){	
		
	var name  = _markers[id].name; 	
	var text = _markers[id].listText_detail;
	
	$("div#facility-detail").html(text);		
	_listCanvas.hide();
	$("div#facility-detail").show();
	
	if(_markers.length > 1)
		$("a#map-all-link").show();
	
}

/**
 * Create error list element if no marker shown
 */
function tx_jo_googlemaps_createErrorBox(){
	tx_jo_googlemaps_removeErrorBox();
	var text = 	"In Ihrem gewählten Kartenausschnitt gibt es leider keine Treffer. Bitte verschieben Sie den Kartenausschnitt oder wählen Sie eine andere Zoomstufe, um Einrichtungen anzuzeigen.";

	var element = jQuery('<li/>').html(text);
	element.attr("id","errorbox");
	element.addClass("error");
	_listCanvas.append(element);
}

/**
 * remove list element
 * 
 * @param int id	markerId
 */
function tx_jo_googlemaps_removeElementById(id){
	var ele = $("#"+id);
	if (ele != null){
		ele.remove();
	}
}

/**
 * remove errorbox
 */
function tx_jo_googlemaps_removeErrorBox(){
	var ele = $("#errorbox");
	if (ele != null){
		ele.remove();
	}
}


function tx_jo_googlemaps_refreshHeader(viewmode){
	$(".header-selection h3").remove();
		
	var text = "";
	var dMlemgth = _drawedMarkers.length;
	if (dMlemgth == 0){
		text += "Keine Treffer !";
	} else {
		if(viewmode == 'list') {
			if(_markers.length < 2) {
				// only one marker exists
				$("div.ce-gmap div.header-selection").hide();
			} else {
				text += dMlemgth + ' ' + _tx_googlemaps_LL.result_kind;
			}
		
		} else {
			text += dMlemgth + ' ' + _tx_googlemaps_LL.result_of + ' ' + _markers.length + ' ' + _tx_googlemaps_LL.result_kind;
		}
	}
	var element = jQuery('<h3/>').html(text);
	_header.prepend(element);
}

function tx_jo_googlemaps_setCenter(){
//	console.log('spst:tx_jo_googlemaps_setCenter');

//	console.log('_markers.length: ' + _markers.length);
	if(_markers.length > 0) {
		var minLat = 0;
		var maxLat = 0;
		var minLng = 0;
		var maxLng = 0;
		var i = 0;
	
		// recalculate proper viewport boundaries based on active markers
		while (i<_markers.length){
//			console.log(i + ': ' + _markers[i].point.lat + ', ' + _markers[i].point.lng);
			if(parseFloat(_markers[i].point.lat) <= minLat || minLat == 0) minLat = parseFloat(_markers[i].point.lat);
			if(parseFloat(_markers[i].point.lat) > maxLat) maxLat = parseFloat(_markers[i].point.lat);
			if(parseFloat(_markers[i].point.lng) <= minLng || minLng == 0) minLng = parseFloat(_markers[i].point.lng);
			if(parseFloat(_markers[i].point.lng) > maxLng) maxLng = parseFloat(_markers[i].point.lng);
//			console.log('minLat, maxLat, minLng, maxLng: ' + minLat + ', ' + maxLat + ', ' + minLng + ', ' + maxLng);
			i++;
		}
		maxLat = maxLat + 0.4; // add a top margin so that the bubble of the highest pint is visible 
//		console.log('minLat, maxLat, minLng, maxLng: ' + minLat + ', ' + maxLat + ', ' + minLng + ', ' + maxLng);

		var corner1 = new GLatLng(minLat,minLng);
		var corner2 = new GLatLng(maxLat,maxLng);
		_bounds = new GLatLngBounds(corner1,corner2);
	
		// calculate and set proper zoom level
		var zoomToFit =  _map.getBoundsZoomLevel(_bounds);
		if(zoomToFit > 9) {
			zoomToFit = 9; // set max zoom level for proper display with only one point
		}
		
		// center the viewport
		_map.setCenter(_bounds.getCenter(),zoomToFit); 
//		console.log('spst:tx_jo_googlemaps_setCenter:_map.setCenter, zoomToFit: ' + zoomToFit);
	}else{
//		console.log('no markers available, _markers.length: ' + _markers.length);
	}
}


