// Mapa genérico que recibe la latitud y longitud
function GenericMap (longitudeCenter,latitudeCenter,nameMap,zoomPercentage) {
  
  // El mapa genérico
  this.map = null;
  
  // El nombre del mapa
  this.name = nameMap;

  // Las coordenadas por defecto
  this.latitudeCenter   = latitudeCenter;
  this.longitudeCenter  = longitudeCenter;
  
  // El porcentaje de zoom
  this.zoom = zoomPercentage;
  
  // Los niveles máximos de zoom para cada plataforma
  this.MAX_ZOOM_BING  = 19;
  this.MAX_ZOOM_YAHOO = 16; // Inverso
  this.MAX_ZOOM_GOOGLE= 19;
  this.MAX_ZOOM_OSM   = 18; // Inverso
  
  
  // El array de los marcadores genéricos
  this.markers = new Array();
  
  this.addMarker = function (genericMarker) {
    this.markers.push(genericMarker);
  }
  this.getMarkers = function () {
    return this.markers;
  }
  
  /*
   * Crea un mapa de Google
   */   
  this.createMapGoogle = function (idMapDiv) {
  
    // Calcula el nivel de zoom en función del porcentaje expresado
    var zoomLevel = Math.floor(this.zoom * this.MAX_ZOOM_GOOGLE / 100);

    var latlng = new google.maps.LatLng(this.latitudeCenter, this.longitudeCenter);
    
    var myOptions = {
      zoom: zoomLevel,
      center: latlng,
      navigationControl: true,
      mapTypeControl: true,
      scaleControl: true,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    this.map = new google.maps.Map(document.getElementById(idMapDiv), myOptions);
    
    this.setAllMarkersOnGoogleMap();

    return this.map;
  }
  
  /*
   * Mete los marcadores en el mapa de Google
   */   
  this.setAllMarkersOnGoogleMap = function() {
    // Mete todos los puntos que ha obtenido
    for (var i=0 ; i<this.markers.length ; i++) {
      var marker = this.markers[i];
      marker.createMarkerGoogle(this.map);
    }  
  }
  
  /*
   * Crea un mapa de Yahoo!
   */
  this.createMapYahoo = function (idMapDiv) {
    
    // Calcula el nivel de zoom en función del porcentaje expresado
    var zoomLevel = this.MAX_ZOOM_YAHOO - Math.floor(this.zoom * this.MAX_ZOOM_YAHOO / 100) + 1;
    
    this.map = new YMap(document.getElementById(idMapDiv));  
    
    // Add map type control  
    this.map.addTypeControl();
    // Add map zoom (long) control  
    this.map.addZoomLong();  
    // Add the Pan Control  
    this.map.addPanControl();  
    
    // Set map type to either of: YAHOO_MAP_SAT, YAHOO_MAP_HYB, YAHOO_MAP_REG  
    this.map.setMapType(YAHOO_MAP_REG);  
    
    
    var geoPoint = new YGeoPoint( this.latitudeCenter, this.longitudeCenter );
    // Display the map centered on a geocoded location  
    this.map.drawZoomAndCenter(geoPoint, zoomLevel);    
    //this.map.addMarker(geoPoint);  
    
    this.setAllMarkersOnYahooMap();
    return this.map;  
    
  }
  
  /*
   * Mete los marcadores en el mapa de Yahoo
   */   
  this.setAllMarkersOnYahooMap = function() {
    // Mete todos los puntos que ha obtenido
    for (var i=0 ; i<this.markers.length ; i++) {
      var marker = this.markers[i];
      marker.createMarkerYahoo(this.map);
    }  
  }  
  
  /*
   * Crea un mapa de OpenStreetMaps
   */   
  this.createMapOSM = function (idMapDiv) {
      
      // Calcula el nivel de zoom en función del porcentaje expresado
      var zoomLevel = Math.floor(this.zoom * this.MAX_ZOOM_OSM / 100); 
      
      this.map = new OpenLayers.Map(idMapDiv, {
          controls: [
              new OpenLayers.Control.Navigation(),
              new OpenLayers.Control.PanZoomBar(),
              new OpenLayers.Control.LayerSwitcher({'ascending':false}),
              new OpenLayers.Control.Permalink(),
              new OpenLayers.Control.ScaleLine(),
              new OpenLayers.Control.Permalink('permalink'),
              new OpenLayers.Control.MousePosition(),
              new OpenLayers.Control.OverviewMap(),
              new OpenLayers.Control.KeyboardDefaults()
          ],
          numZoomLevels: this.MAX_ZOOM_OSM
      });

      // Define the map layer
      // Note that we use a predefined layer that will be
      // kept up to date with URL changes
      // Here we define just one layer, but providing a choice
      // of several layers is also quite simple
      // Other defined layers are OpenLayers.Layer.OSM.Mapnik, OpenLayers.Layer.OSM.Maplint and OpenLayers.Layer.OSM.CycleMap
      
      layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
      this.map.addLayer(layerMapnik);
      var layerTilesAtHome = new OpenLayers.Layer.OSM.Osmarender("Osmarender");
      this.map.addLayer(layerTilesAtHome);
      var layerCycleMap = new OpenLayers.Layer.OSM.CycleMap("CycleMap");
      this.map.addLayer(layerCycleMap);


      this.map.addControl(new OpenLayers.Control.LayerSwitcher());
      
      var markerLayer  = new OpenLayers.Layer.Markers(this.name);
      this.map.addLayer(markerLayer);
      
      var lonLat = new OpenLayers.LonLat(this.longitudeCenter, this.latitudeCenter).transform(new OpenLayers.Projection("EPSG:4326"), this.map.getProjectionObject());
      this.map.setCenter (lonLat, zoomLevel);
      
      this.setAllMarkersOnOSMap(markerLayer);
  }

  /*
   * Mete los marcadores en el mapa de OSM
   */   
  this.setAllMarkersOnOSMap = function(markerLayer) {
    // Mete todos los puntos que ha obtenido
    for (var i=0 ; i<this.markers.length ; i++) {
      var marker = this.markers[i];
      marker.createMarkerOSM(this.map,markerLayer);
    }  
  }
   
  /*
   * Crea un mapa de Bing
   */   
  this.createMapBing = function (idMapDiv) {
    // Calcula el nivel de zoom en función del porcentaje expresado
    var zoomLevel = Math.floor(this.zoom * this.MAX_ZOOM_BING / 100);

    var latLong = new VELatLong(this.latitudeCenter, this.longitudeCenter);
    this.map = new VEMap(idMapDiv);
    this.map.LoadMap(latLong, zoomLevel ,'h' ,false);
    
    this.setAllMarkersOnBingMap();
  }  

  /*
   * Mete los marcadores en el mapa de Bing
   */   
  this.setAllMarkersOnBingMap = function() {
    // Mete todos los puntos que ha obtenido
    for (var i=0 ; i<this.markers.length ; i++) {
      var marker = this.markers[i];
      marker.createMarkerBing(this.map);
    }  
  }
}




// Clase imagen            
function ImageIcon (width, height, src) {
    this.width = width;
    this.height = height;
    this.src = src;
}




// Clase Marcador Genérico
function GenericMarker (longitude, latitude, title, htmlContent, icon) {

    this.latitude = latitude;
    this.longitude = longitude;
    this.icon = icon;
    this.htmlContent = htmlContent;
    this.title = title;

    this.createMarkerGoogle = function (map) {
        var customIcon = null;
        if (this.icon) {
            customIcon = new google.maps.MarkerImage(
                    this.icon.src,
                    new google.maps.Size(this.icon.width, this.icon.height),
                    // The origin for this image 
                    new google.maps.Point(0,0),             
                    // The anchor for this image 
                    new google.maps.Point(this.icon.width/2,this.icon.height));
        }
        
        var point = new google.maps.LatLng(this.latitude,this.longitude);
        
        var marker = new google.maps.Marker({
          position: point, 
          map: map, 
          icon: customIcon,
          title: this.title
        });        

        // Añade el soporte para abrir los diálogos
        var infowindow = new google.maps.InfoWindow({
          content: this.htmlContent
          });

        google.maps.event.addListener(marker, 'click', function() {
          infowindow.open(map,marker);
          });

        return marker;
    }
    
    /*
     * Crea un marcador para Yahoo!
     */     
    this.createMarkerYahoo = function (map) {

        var geoPoint = new YGeoPoint( this.latitude, this.longitude );

        var imageIco = null;
        if (this.icon) {
          imageIco = new YImage();  
          imageIco.src = this.icon.src;  
          imageIco.size = new YSize(this.icon.width,this.icon.height);  
          imageIco.offsetSmartWindow = new YCoordPoint(0, 0);
        }  
  
        var newMarker= new YMarker(geoPoint, imageIco);  
        newMarker.addAutoExpand(this.title);  
        var htmlMarkup = this.htmlContent;
        YEvent.Capture(newMarker, EventsList.MouseClick,   
          function(){  
            newMarker.openSmartWindow(htmlMarkup);  
           });  
        map.addOverlay(newMarker);  
    }
    
    /*
     * Crea un marcador para OSM
     */
    this.createMarkerOSM = function(map, markerLayer) {

        
        // La dirección del icono y su tamaño
        var icon = null;
        if (this.icon) {
        // Tamaño del icono del marcador
          var size = new OpenLayers.Size(this.icon.width,this.icon.height);
          var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
          icon = new OpenLayers.Icon(this.icon.src,size,offset);
        }
        
        // Lo sitúa en unas coordenadas
        var markerLonLat = new OpenLayers.LonLat(this.longitude, this.latitude).transform(new OpenLayers.Projection("EPSG:4326"), map.getProjectionObject());


        var feature = new OpenLayers.Feature(markerLayer, markerLonLat);
        
         
        feature.closeBox = true;
        feature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
            'autoSize': true
        });
        feature.data.popupContentHTML = this.htmlContent;
        feature.data.overflow = (this.overflow) ? "auto" : "hidden";

        // Función que gestiona los clicks de los marcadores
        var markerClick = function (evt) {
            if (this.popup == null) {
                this.popup = this.createPopup(this.closeBox);
                map.addPopup(this.popup);
                this.popup.show();
            } else {
                this.popup.toggle();
            }
            currentPopup = this.popup;
            OpenLayers.Event.stop(evt);
        };

        var marker = feature.createMarker();
        if (icon) {
          //marker.icon = icon;
        }
        //marker.setOpacity(0.2);
        

        marker.events.register("mousedown", feature, markerClick);

        markerLayer.addMarker(marker);      
                             
        return (marker);                    
    }
    
    /*
     * Crea un marcador para Bing
     */
    this.createMarkerBing = function(map) {
        var latLong = new VELatLong(this.latitude, this.longitude);

        var shape = new VEShape(VEShapeType.Pushpin, latLong);
        shape.SetTitle(this.title);
        shape.SetDescription(this.htmlContent);

        if (this.icon) {
          shape.SetCustomIcon(
            "<span><img src='" + this.icon.src +"'/></span>");
  
          shape.ImageOffset= new VEPixel(this.icon.width/2, this.icon.height);
        }
        
        map.AddShape(shape);
        return shape;
    }

    
    
}

