/*
* http://code.google.com/intl/es-ES/apis/maps/documentation/javascript/reference.html
*/
var markersArray = new Array();
var mapsArray = new Array();
var mapsInfoWindowArray = new Array();
var mapGeocoder = new google.maps.Geocoder();
var mapDefaultGetMarkerFunc = mapGetMarker;

var mapDirectionsDisplayArray = new Array();
var mapDirectionsService = new google.maps.DirectionsService();
var mapDirectionsJOINDisplayArray = new Array();

var GOOGLEMAPS_TYPE_ROADMAP = google.maps.MapTypeId.ROADMAP;
var GOOGLEMAPS_TYPE_SATELLITE = google.maps.MapTypeId.SATELLITE;
var GOOGLEMAPS_TYPE_HYBRID = google.maps.MapTypeId.HYBRID;
var GOOGLEMAPS_TYPE_TERRAIN = google.maps.MapTypeId.TERRAIN;

var GOOGLEMAPS_ADD_MARKER_AUTO_CLEAR = 1; 
var GOOGLEMAPS_ADD_MARKER_AUTO_JOIN = 2; 
var GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS = 3; 
var GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE = 1;

var GOOGLEMAPS_FIT_MODE_ALL_MARKS = 1; 
var GOOGLEMAPS_FIT_MODE_CENTER_NEW_MARK = 2; 
var GOOGLEMAPS_DEFAULT_FIT_MODE = 2;
	
var GOOGLEMAPS_DEFAULT_ZOOM = 15;
var GOOGLEMAPS_ALLOW_CLICK = true;

function mapEvalDefault(mapDest){
	if(mapDest == null){
		if(mapsArray.length > 0){
			return mapsArray[(mapsArray.length-1)].map;
		}else{
			return null;
		}
	}else{
		for(i in mapsArray){
			if(mapsArray[i].name == mapDest){
				return mapsArray[i].map;
			}
		}
		return false;
	}
}

function mapGetNameByMap(mapDest){
	for(i in mapsArray){
		if(mapsArray[i].map == mapDest){
			return mapsArray[i].name;
		}
	}
	return false;
}

function mapDestroy(mapDest){
	if(mapDest == null){
		if(mapsArray.length > 0){
			mapsArray[(mapsArray.length-1)].map = null;
			return mapsArray.splice((mapsArray.length-1),1);
		}else{
			return null;
		}
	}else{
		for(i in mapsArray){
			if(mapsArray[i].name == mapDest){
				mapsArray[i].map = null;
				return mapsArray.splice(i,1);
			}
		}
		return false;
	}
}

function mapResize(mapDest){
	mapDest = mapEvalDefault(mapDest);
	google.maps.event.trigger(mapDest,'resize');
	mapDest.setZoom(mapDest.getZoom());
}

function mapGetLatLngBounds(mapDest){
	for(i in mapsArray){
		if(mapsArray[i].name == mapDest){
			return mapsArray[i].bounds;
		}
	}
	if(mapsArray.length > 0){
		return mapsArray[(mapsArray.length-1)].bounds;
	}else{
		return null;
	}
}

function mapGetPosInArray(mapDest){
	if(mapsArray.length > 0){
		for(i in mapsArray){
			if(mapsArray[i].name == mapDest){
				return i;
			}
		}
	}
	return false;
}

// CANVIA EL TIPO DEL MAPA
function mapChangeType(type,mapDest){
	mapDest = mapEvalDefault(mapDest);
	// ROADMAP,SATELLITE,HYBRID,TERRAIN
	mapDest.setMapTypeId(type);
}

/*
 * FUNCTIONS ABOUT DIRECTIONS
 */
function mapCreateDirectionDisplay(name,mapStr,noinsert){

	if(noinsert == null) noinsert = false;
	
	var map = mapEvalDefault(mapStr);
	
	var directionsDisplay = new google.maps.DirectionsRenderer({
		markerOptions:{
			animation: google.maps.Animation.DROP,
			draggable: true
		},
		suppressMarkers: true,
		preserveViewport: true
	});
	directionsDisplay.setMap(map);

	if(!noinsert) mapDirectionsDisplayArray.push({name:name,direction:directionsDisplay,map:mapStr});

	return directionsDisplay;
	
}
function mapDirectionEvalDefault(mapDest){
	if(mapDest == null){
		if(mapDirectionsDisplayArray.length > 0){
			return mapDirectionsDisplayArray[(mapDirectionsDisplayArray.length-1)].direction;
		}else{
			return null;
		}
	}else{
		for(i in mapDirectionsDisplayArray){
			if(mapDirectionsDisplayArray[i].name == mapDest){
				return mapDirectionsDisplayArray[i].direction;
			}
		}
		return false;
	}
}
function mapUpdateDisplayDirections(){
	
	var start = "";
	var end = "";
	
	if(markersArray.length >= 2){
		
		var mark = mapGetMarkerByArrayPosition((markersArray.length-1));
		var mapName = mapGetNameByMap(mapGetMapByMarker(mark));
		
		if(mapDirectionsDisplayArray.length == 0){			
			mapCreateDirectionDisplay(mapName+"_direction_"+mapDirectionsDisplayArray.length,mapName);
		}
		
		for(var j = 0;j<mapDirectionsDisplayArray.length;j++){

			var waypts = new Array();
			var first = (j*10);

			if(markersArray.length > first){
						
				if(j >= 1){
					
					var dir;

					var numDisplayJOIN = (j-1);

					if(j <= mapDirectionsJOINDisplayArray.length){
						dir = mapDirectionsJOINDisplayArray[numDisplayJOIN];
					}else{
						dir = mapCreateDirectionDisplay(mapName+"_direction_join_"+mapDirectionsJOINDisplayArray.length,mapName,true);
						mapDirectionsJOINDisplayArray.push(dir);
					}
	
					var mark = mapGetMarkerByArrayPosition(first);
					
					var request = {
					    origin: end, 
						destination: mark.getPosition().lat()+","+mark.getPosition().lng(),
					   	waypoints: waypts,
						optimizeWaypoints: false,
						provideRouteAlternatives:true,
						travelMode: google.maps.DirectionsTravelMode.DRIVING
					};
					mapDirectionsService.route(request, function(response, status) {
						if(status == google.maps.DirectionsStatus.OK) {
							dir.setDirections(response);
						}
					});
														
				}
							
				var last = (j*10)+10;
				if(last > markersArray.length) last = markersArray.length;
	
				if(markersArray.length > last && j == (mapDirectionsDisplayArray.length-1)){
					last = markersArray.length;
				}
				
				for(var i = first;i<last;i++){
					var mark = mapGetMarkerByArrayPosition(i);
					
					if(markersArray[i].ico != "") mark.setIcon(markersArray[i].ico);
					
					if(i == first) start = mark.getPosition().lat()+","+mark.getPosition().lng();
					else if(i == (last-1)) end = mark.getPosition().lat()+","+mark.getPosition().lng();
					else waypts.push({location:mark.getPosition().lat()+","+mark.getPosition().lng(),stopover:false});
				}
				mapCalculateRoute(j,start,end,waypts);

			}
				
		}
		
	}else if(markersArray.length == 1){
		var mark = mapGetMarkerByArrayPosition(0);
		if(markersArray[0].ico != "") mark.setIcon(markersArray[0].ico);
	}

	if(mapDirectionsDisplayArray.length > 0){
		var numDisplays;
		if(markersArray.length == 1) numDisplays = 0;
		else numDisplays = Math.ceil((markersArray.length/10));
		if(mapDirectionsDisplayArray.length > numDisplays){
			for(var b = numDisplays;b<mapDirectionsDisplayArray.length;b++){
				mapDirectionsDisplayArray[b].direction.setMap(null);
				mapDirectionsDisplayArray[b].direction = null;
			}
			mapDirectionsDisplayArray.splice(numDisplays,(mapDirectionsDisplayArray.length-numDisplays));
		}
	}

	if(mapDirectionsJOINDisplayArray.length > 0){
		if(mapDirectionsJOINDisplayArray.length >= (mapDirectionsDisplayArray.length-1)){
			for(var z = (mapDirectionsDisplayArray.length-1);z<mapDirectionsJOINDisplayArray.length;z++){
				mapDirectionsJOINDisplayArray[z].setMap(null);
				mapDirectionsJOINDisplayArray[z] = null;
			}
			mapDirectionsJOINDisplayArray.splice((mapDirectionsDisplayArray.length-1),(mapDirectionsJOINDisplayArray.length-(mapDirectionsDisplayArray.length-1)));
		}
	}
	
}

function mapCalculateRoute(num,start,end,waypts){

	var mark = mapGetMarkerByArrayPosition((markersArray.length-1));
	var mapName = mapGetNameByMap(mapGetMapByMarker(mark));
	
	var request = {
	    origin: start, 
	    destination: end,
	    waypoints: waypts,
		optimizeWaypoints: false,
		provideRouteAlternatives:true,
		travelMode: google.maps.DirectionsTravelMode.DRIVING
	};
	mapDirectionsService.route(request, function(response, status) {
		if (status == google.maps.DirectionsStatus.OK) {
	    	mapDirectionEvalDefault(mapName+"_direction_"+num).setDirections(response);
			/*
			var route = response.routes[0];
			var summaryPanel = document.getElementById("directions_panel");
			summaryPanel.innerHTML = "";
	        // For each route, display summary information.
	        for (var i = 0; i < route.legs.length; i++) {
	          var routeSegment = i + 1;
	          summaryPanel.innerHTML += "<b>Route Segment: " + routeSegment + "</b><br />";
	          summaryPanel.innerHTML += route.legs[i].start_address + " to ";
	          summaryPanel.innerHTML += route.legs[i].end_address + "<br />";
	          summaryPanel.innerHTML += route.legs[i].distance.text + "<br /><br />";
	        }
	        */
		}else if(status == google.maps.DirectionsStatus.MAX_WAYPOINTS_EXCEEDED){
			var mark = mapGetMarkerByArrayPosition((markersArray.length-1));
			mapCreateDirectionDisplay(mapName+"_direction_"+mapDirectionsDisplayArray.length,mapName);			
			mapUpdateDisplayDirections();
		}else if(status == google.maps.DirectionsStatus.ZERO_RESULTS){
			var mark = mapGetMarkerByArrayPosition((markersArray.length-1));
			mapDeleteMarkers(mark,mapName);
			mapUpdateDisplayDirections();
			$("#GM_DISPATCHER").trigger("GM_EVENT_DIRECTIONS_INVALID_MARKER_POSITION",status);
		}else{
			$("#GM_DISPATCHER").trigger("GM_EVENT_DIRECTIONS_CALCULATE_ROUTE_ERROR",status);
		}
	});
	
}

function mapDirectionsMarkerAdded(marker,lat,lng){
	mapUpdateDisplayDirections();
}
function mapDirectionsMarkerClicked(marker){
	mapDeleteMarkers(marker,mapGetMapByMarker(marker));
}
function mapDirectionsMarkerUpdate(marker,lat,lng){
	mapUpdateDisplayDirections();
}

/*
 * FUNCTIONS ABOUT MARKERS
 */
function mapMarkersRefreshIcos(){
	for(var j = 0;j<markersArray.length;j++){
		markersArray[j].mark.setIcon(markersArray[j].ico);
	}
}
function mapAddMarker(theMarker,infoWindow,mapDest,params,noDispatch){
	
	if(!noDispatch) noDispatch = false;
	
	var mapBounds = mapGetLatLngBounds(mapDest);
	mapDest = mapEvalDefault(mapDest);
		
	if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_AUTO_CLEAR){
		mapDeleteMarkers();
	}
	
	markersArray.push({mark:theMarker,map:mapDest,ico:""});
	
	if(params){
		for(var prop in params){
			markersArray[(markersArray.length-1)][prop] = params[prop];
		}
	}
	
	theMarker.setMap(mapDest);
	
	mapBounds.extend(theMarker.getPosition());
	
	if(!noDispatch) $("#GM_DISPATCHER").trigger("GM_EVENT_MARKER_ADDED",[theMarker.getPosition().lat(),theMarker.getPosition().lng()]);
	if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapDirectionsMarkerAdded(theMarker,theMarker.getPosition().lat(),theMarker.getPosition().lng());
	
	if(GOOGLEMAPS_ALLOW_CLICK){
		
		if(infoWindow != null){
			google.maps.event.addListener(theMarker, "click", function() {
				infoWindow.open(mapDest,theMarker);
				$("#GM_DISPATCHER").trigger("GM_EVENT_MARKER_CLICKED",theMarker);
				if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapDirectionsMarkerClicked(theMarker);
			});
		}else{
			google.maps.event.addListener(theMarker, "click", function() {		
				$("#GM_DISPATCHER").trigger("GM_EVENT_MARKER_CLICKED",theMarker);
				if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapDirectionsMarkerClicked(theMarker);
			});
		}
	
		google.maps.event.addListener(theMarker, "dragend", function(e) {
			$("#GM_DISPATCHER").trigger("GM_EVENT_MARKER_UPDATE",[theMarker,e.latLng.lat(),e.latLng.lng()]);
			if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapDirectionsMarkerUpdate(theMarker,e.latLng.lat(),e.latLng.lng());
		});
		
	}
	
}
function mapGetMarkerPosition(marker){
	return marker.getPosition();
}
function mapUpdateMarkerPosition(marker,lat,lng){
	marker.setPosition(new google.maps.LatLng(lat,lng));
	$("#GM_DISPATCHER").trigger("GM_EVENT_MARKER_UPDATE",[marker,lat,lng]);
	if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapDirectionsMarkerUpdate(marker,lat,lng);
}

// ELIMINA LOS MARCADORES DEL MAPA PERO LOS MANTIENE EN EL ARRAY / PODEMOS PASAR UN ELEMENTO PARA SOLO ELIMINARLO A EL
function mapClearMarkers(theMarker,mapDest){
	var mapBounds = mapGetLatLngBounds(mapDest);
	mapDest = mapEvalDefault(mapDest);
	if(markersArray && markersArray.length > 0){
		for(i in markersArray) {
			if(theMarker == null || markersArray[i].mark == theMarker){
				markersArray[i].mark.setMap(null);
				if(theMarker != null){
					break;
				}
			}
		}
	}
}
// MUESTRA LOS MARCADORES QUE EXISTEN EN EL ARRAY / PODEMOS PASAR UN ELEMENTO PARA SOLO MOSTRARLO A EL
function mapShowMarkers(theMarker,mapDest) {
	mapDest = mapEvalDefault(mapDest);
	if (markersArray && markersArray.length > 0){
		for (i in markersArray) {
			if(theMarker == null || markersArray[i].mark == theMarker){
				markersArray[i].mark.setMap(mapDest);
				if(theMarker != null){
					break;
				}
			}
		}
	}
}
function mapGetMapByMarker(theMarker) {
	if (markersArray && markersArray.length > 0){
		for (i in markersArray) {
			if(markersArray[i].mark == theMarker){
				return markersArray[i].map;
			}
		}
	}
}
// ELIMINA LOS MARCADORES Y LOS ELIMINA DEL ARRAY / PODEMOS PASAR UN ELEMENTO PARA SOLO ELIMINARLO A EL
function mapDeleteMarkers(theMarker,mapDest) {
	var pos = mapGetPosInArray(mapDest);
	if(markersArray && markersArray.length > 0) {
		for (i in markersArray) {
			if(theMarker == null || markersArray[i].mark == theMarker){
				markersArray[i].mark.setMap(null);
				if(theMarker != null){
					markersArray.splice(i,1);
					break;
				}
			}
		}
		if(theMarker == null){
			markersArray.length = 0;
			if(pos != false) mapsArray[pos].bounds = new google.maps.LatLngBounds();
		}					
	}
	if(GOOGLEMAPS_DEFAULT_ADD_MARKER_TYPE == GOOGLEMAPS_ADD_MARKER_DISPLAY_DIRECTIONS) mapUpdateDisplayDirections();
}
function mapRemoveAllMarkers(mapDest){
	mapDeleteMarkers(null,mapDest);
	mapUpdateDisplayDirections();
}
function mapGetMarkerPosInArray(mark){
	if(markersArray.length > 0){
		for(i in markersArray){
			if(markersArray[i].mark == mark){
				return i;
			}
		}
	}
	return false;
}
function mapGetMarkerByArrayPosition(pos){
	if(markersArray && markersArray.length > pos) {
		return markersArray[pos].mark;
	}
}
function mapGetMarker(coordPoint,title,draggable,icon,props){
	if(draggable == null) draggable = true;
	
	if(GOOGLEMAPS_ALLOW_CLICK == false) draggable = false;
	
	var marker = new google.maps.Marker({
		position: coordPoint,
		animation: google.maps.Animation.DROP,
		draggable: draggable
	});
	if(title != null) marker.setTitle(title);
	if(icon != null) marker.setIcon(icon);			
	if(draggable != null){
		if(draggable){
			google.maps.event.addListener(marker,'click',function(){
				if(marker.getAnimation() != null) {
			    	marker.setAnimation(null);
			    }else{
			    	marker.setAnimation(google.maps.Animation.BOUNCE);
			    }
			});
		}
	}			
	return marker;
}
function mapAddMarkersByCoordsArray(arr,mapDest){
	for(var i = 0;i<arr.length;i++){
		var marker = mapDefaultGetMarkerFunc(mapGetPositionPoint(arr[i].lat,arr[i].lng));
		mapAddMarker(marker,null,mapDest,arr[i].params,true);
	}
}
/*
* END FUNCTIONS ABOUT MARKERS
*/

function mapGetInfoWindow(contentString){
	var infoW = new google.maps.InfoWindow({
	    content: contentString,
        maxWidth: 300
	});
	mapsInfoWindowArray.push(infoW);
	return infoW;
}

// DEVUELVE UN OBJETO DEL TIPO LATLNG DE GOOGLE CON LA LATITUD Y LONGITUD PASADAS
function mapGetPositionPoint(lat,lng){
	return new google.maps.LatLng(lat,lng);
}

function mapPanToPosition(mapDest,lat,lng){
	mapDest = mapEvalDefault(mapDest);
	mapDest.panTo(new google.maps.LatLng(lat,lng));
}

function mapAutoFit(mapDest){
	
	if(markersArray.length > 0){
	
		var mapBounds = mapGetLatLngBounds(mapDest);
		mapDest = mapEvalDefault(mapDest);
	  	
		if(GOOGLEMAPS_DEFAULT_FIT_MODE == GOOGLEMAPS_FIT_MODE_CENTER_NEW_MARK){
			mapDest.setCenter(markersArray[(markersArray.length-1)].mark.getPosition());
			mapDest.setZoom(GOOGLEMAPS_DEFAULT_ZOOM);
		}else{
			mapDest.fitBounds(mapBounds);
		}
			
	  	var listener = google.maps.event.addListener(mapDest, "idle", function() { 
			if (mapDest.getZoom() > GOOGLEMAPS_DEFAULT_ZOOM) mapDest.setZoom(GOOGLEMAPS_DEFAULT_ZOOM); 
			google.maps.event.removeListener(listener); 
		});
  	
	}
	
}

function mapSearchAddress(address,mapDest){
	var mapBounds = mapGetLatLngBounds(mapDest);
	var mapDestObj = mapEvalDefault(mapDest);
	if(mapGeocoder) {
		mapGeocoder.geocode({"address": address}, function(results, status) {
			if(status == google.maps.GeocoderStatus.OK) {
				var marker = mapDefaultGetMarkerFunc(results[0].geometry.location,address);
				mapAddMarker(marker,null,mapDest);
				mapAutoFit(mapDest);
			}else{
				alert("Google Maps Geocode no ha podido encontrar la dirección solicitada por la siguiente razón: " + status);
			}
		});
    }
}

function mapDisableStreetView(mapDest){
	mapDest = mapEvalDefault(mapDest);
	mapDest.setOptions({streetViewControl:false});
}

function mapDisableTypes(mapDest){
	mapDest = mapEvalDefault(mapDest);
	mapDest.setOptions({mapTypeControl:false});
	mapDest.setOptions({streetViewControl:false});
}

function mapSetOption(option,value,mapDest){
	mapDest = mapEvalDefault(mapDest);
	mapDest.setOptions({option:value});
}

// INICIALIZA EL OBJETO MAPS
function initialize(div,point,zoom,type,allowClick,latField,lonField){

	if(type == null) type = google.maps.MapTypeId.ROADMAP;
	if(zoom == null) zoom = 1;
	if(point == null) point = mapGetPositionPoint(0,0);
  	  		
	var myOptions = {
		zoom: zoom,
		center: point,
		mapTypeId: type
	};
	
	var mapDest = new google.maps.Map(document.getElementById(div),myOptions);
		
	if (allowClick==true) {
		var listener = google.maps.event.addListener(mapDest, "click", function(event) { 
			var marker = mapDefaultGetMarkerFunc(event.latLng);
			mapAddMarker(marker,null,div);
			$("#GM_DISPATCHER").trigger("GM_EVENT_MAP_CLICKED",event.latLng);
		});
	}
	
	var listener2 = google.maps.event.addListener(mapDest, "tilesloaded", function(event) { 
		google.maps.event.removeListener(listener2);
		$("#GM_DISPATCHER").trigger("GM_EVENT_MAP_LOADED",div);
		mapResize(div);
		
		if(latField != "" && latField != null){
			var latFieldValue = $("#"+latField).val();
			var lonFieldValue = $("#"+lonField).val();
			if(latFieldValue != "" && lonFieldValue != ""){
				mapSearchAddress(latFieldValue+","+lonFieldValue,div);
			}
		}
		
	});
	
	var theLatLngBoundsObj = new google.maps.LatLngBounds();
	
	mapsArray.push({map:mapDest,name:div,bounds:theLatLngBoundsObj});
	
}

var divChild;
$(document).ready(function(){
	divChild = document.createElement("div");
	divChild.id = "GM_DISPATCHER";
	document.getElementsByTagName("body")[0].appendChild(divChild);
});
