ClusterMarker.prototype._clusterMarker=function($clusterGroupIndexes){
  function $newClusterMarker($location, $icon, $title){
    return new GMarker($location, {icon:$icon, title:$title});
  }
  var $clusterGroupBounds=new GLatLngBounds(), i, $clusterMarker, $clusteredMarkers=[], $marker, $this=this, $mapMarkers=this._mapMarkers;
  for(i=$clusterGroupIndexes.length-1; i>=0; i--){
    $marker=$mapMarkers[$clusterGroupIndexes[i]];
    $marker.index=$clusterGroupIndexes[i];
    $clusterGroupBounds.extend($marker.getLatLng());
    $clusteredMarkers.push($marker);
  }
  $clusterMarker=$newClusterMarker($clusterGroupBounds.getCenter(), this.clusterMarkerIcon, this.clusterMarkerTitle.replace(/%count/gi, $clusterGroupIndexes.length));
  $clusterMarker.clusterGroupBounds=$clusterGroupBounds;  //  only req'd for default cluster marker click action
  this._eventListeners.push(GEvent.addListener($clusterMarker, 'click', function(){
    $this.clusterMarkerClick({clusterMarker:$clusterMarker, clusteredMarkers:$clusteredMarkers });
  }));
  $clusterMarker._childIndexes=$clusterGroupIndexes;
  for(i=$clusterGroupIndexes.length-1; i>=0; i--){
    $mapMarkers[$clusterGroupIndexes[i]]._parentCluster=$clusterMarker;
  }
  return $clusterMarker;
};

ClusterMarker.prototype.refresh=function($forceFullRefresh){
  var i, $marker, $zoomLevel=this._map.getZoom(), $uncachedIconBoundsIndexes=this._filterActiveMapMarkers();
  if(this._activeMarkersChanged || $forceFullRefresh){
    this._removeClusterMarkers();
    if(this.clusteringEnabled && $zoomLevel<this._map.getCurrentMapType().getMaximumResolution()){
      if($uncachedIconBoundsIndexes.length>0){
        this._preCacheIconBounds($uncachedIconBoundsIndexes, $zoomLevel);
      }
      this._filterIntersectingMapMarkers();
    }
    for(i=this._clusterMarkers.length-1; i>=0; i--){
      this._map.addOverlay(this._clusterMarkers[i]);
    }
    for(i=this._mapMarkers.length-1; i>=0; i--){
      $marker=this._mapMarkers[i];
      if(!$marker._isVisible && $marker._makeVisible){
        this._map.addOverlay($marker);
        $marker._isVisible=true;
      }
      if($marker._isVisible && !$marker._makeVisible){
        this._map.removeOverlay($marker);
        $marker._isVisible=false;
      }
    }
  }
};

var mmEmbeddedMap = {

  // Google map object
  map: {},

  // ClusterMarker
  cluster: {},

  // initial datas
  _mapIds: [],

  // current marker datas
  _defaultMarker: null,
  
  // URLs
  _mapMarkersUrl: '',
  _markerMediasUrl: '',
  _frontmapUrl: '',
  
  browseMedias: function(marker) {
    mmMediaBrowser.show(marker); 
  },
  
  // object initialization
  init: function(gmapnode, mapIds, marker, clusterMarkerTitle, mapMarkersUrl, markerMediasUrl, frontmapUrl) {

    // refers this as self in order to keep object context across external methods/events calls
    //self = this;
    
    // attributes setting
    this._mapIds = mapIds;
    
    if(marker)
    {
      this._defaultMarker = this._marker = this.createMarker(marker);
    }
    
    this._mapMarkersUrl = mapMarkersUrl;
    this._markerMediasUrl = markerMediasUrl;
    this._frontmapUrl = frontmapUrl;
    
    // instantiate map
    this.map = new GMap2(document.getElementById(gmapnode));
    
    // define Hybrib map
    this.map.setMapType(G_HYBRID_MAP);
    
    // enable scroll Zoom
    this.map.enableScrollWheelZoom();
    
    this.map.addControl(new GSmallMapControl(), new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(10,40)));
    
    // create GIcon for markers
    this.defaultIcon = new GIcon(G_DEFAULT_ICON);
    this.defaultIcon.image = '/images/cluster.png';
    this.defaultIcon.iconSize = new GSize(32,32);
    this.defaultIcon.iconAnchor = new GPoint(16,16);
    
    this.cluster = new ClusterMarker(this.map, {clusterMarkerIcon: this.defaultIcon, clusterMarkerTitle: clusterMarkerTitle} );
    
    if(this._mapIds.length) {      
      this.updateMarkers();
    }
    else {
      this.cluster.addMarkers(this.getDefaultMarkers());
      this.fitMapToMarkers();
      if(this._defaultMarker.data['DEFAULT_MEDIA_ID']) {
        GEvent.trigger(this._defaultMarker, 'click');
      }
    }
  },

  createMarker: function(json) {
    var markerIcon = new GIcon(G_DEFAULT_ICON);
    markerIcon.image = '/images/t' + json['MAR_TYPE'] + '.png';
    markerIcon.iconSize = new GSize(32,32);
    markerIcon.iconAnchor = new GPoint(16,16);
    var marker = new GMarker(new GLatLng(json['MAR_LAT'], json['MAR_LON']), {icon: markerIcon, title: json['MAR_TITLE']});
    
    marker.data = json;
    
    GEvent.addListener(marker, 'click', function() {
      
      jQuery.getJSON(
          mmEmbeddedMap._markerMediasUrl,
          { markerId: marker.data['MAR_ID'] },
          function(json) {
            marker.data['MEDIAS'] = json;
            mmEmbeddedMap.browseMedias(marker);
          }
        );

      //window.open(self.frontmapUrl + '?mapIds=' + self._mapIds + '&lat=' + this.getLatLng().lat() + '&lng=' + this.getLatLng().lng() + '&zoom=' + (self.map.getZoom() + 1), 'metamap');
    });
    
    return marker;
  },
  
  getDefaultMarkers: function() {
    markers = [];
    
    if(this._defaultMarker) {
      markers[this._defaultMarker.data['MAR_ID']] = this._defaultMarker;
    }
    return markers;
  },
  
  fitMapToMarkers: function() {
    this.cluster.fitMapToMarkers();
    center = this.map.getCenter();

    this.map.getCurrentMapType().getMaxZoomAtLatLng(
      center,
      function(response) {

        if ((response && response['status'] == G_GEO_SUCCESS) && (response['zoom'] < mmEmbeddedMap.map.getZoom())) {
          mmEmbeddedMap.map.setCenter(center, response['zoom']);
        }            
      }
    );
  },
  
  updateMarkers: function(bounds) {
    
    requestParameters = { "mapIds[]": this._mapIds };
    
    if(bounds) {
      requestParameters.swLat = bounds.getSouthWest().lat();
      requestParameters.swLng = bounds.getSouthWest().lng();
      requestParameters.neLat = bounds.getNorthEast().lat();
      requestParameters.neLng = bounds.getNorthEast().lng();
    }
    
    jQuery.getJSON(
      this._mapMarkersUrl,
      requestParameters,
      function(json) {
        
        markers = mmEmbeddedMap.getDefaultMarkers();
        
        for(var i= 0; i < json.length; i++) {
          markers[json[i]['MAR_ID']] = mmEmbeddedMap.createMarker(json[i]);
        }

        mmEmbeddedMap.cluster.removeMarkers();
        mmEmbeddedMap.cluster.addMarkers(markers);
        
        // first call, no bounds given, map is resized to show all markers
        //
        if(!bounds)
        {
          mmEmbeddedMap.fitMapToMarkers();
          // map events    
          GEvent.addListener(mmEmbeddedMap.map, 'moveend', function() {
            mmEmbeddedMap.updateMarkers(mmEmbeddedMap.map.getBounds());
          });
        }
          
        mmEmbeddedMap.cluster.refresh();

      }
    );
  }
}

var mmMediaBrowser = {
  _currentMediaPos: 0,
  _node: null,
  _markerTitleNode: null,
  _mediaTitleNode: null,
  _marker: {},
  _medias: [],
  _feedUrl: null,
  
  init: function(nodeSelector, feedUrl) {
    this._node = jQuery(nodeSelector);
    this._node.hide();

    this._feedUrl = feedUrl;

    this._preview = this._node.find('#media-preview');
    this._markerTitleNode = this._node.find('#marker-title');
    this._mediaTitleNode = this._node.find('#media-title');

    
    // init audio player
    AudioPlayer.setup("/players/audio-player.swf", { width: 290 });
    
    this._node.find('#media-prev').click(function(e) {
      e.preventDefault();
      mmMediaBrowser.previous();
      return false;
    });

    this._node.find('#media-next').click(function(e) {
      e.preventDefault();
      mmMediaBrowser.next();
      return false;
    });
    
    this._node.find('#browser-close').click(function(e) {
      e.preventDefault();
      mmMediaBrowser._node.hide();
      return false;
    });
  },

  setArrowsDisplay: function() {
    
    if(this._mediaCount === 1) {
      this._node.find('#media-prev').hide();
      this._node.find('#media-next').hide();
      return;
    }
    
    if(this._currentMediaPos == 0) {
      this._node.find('#media-prev').hide();
      this._node.find('#media-next').show();
      return;
    }
    
    if(this._currentMediaPos == this._mediaCount - 1) {
      this._node.find('#media-prev').show();
      this._node.find('#media-next').hide();
      return;
    }
    
    this._node.find('#media-prev').show();
    this._node.find('#media-next').show();
    
  },
  
  previous: function() {
    if(this._currentMediaPos > 0) {
      this._currentMediaPos--;
      this.refresh();
    }
  },
  
  next: function() {
    if(this._currentMediaPos < this._mediaCount - 1) {
      this._currentMediaPos++;
      this.refresh();
    }
  },
  
  loading: function() {
  },
  
  show: function(marker) {
    
    this._marker = marker;
    this._medias = marker.data['MEDIAS'];
    this._mediaCount = this._medias.length;

    this._markerTitleNode.text(marker.data['MAR_TITLE']);
    
    if(this._mediaCount === 0) {
      return;
    }
    
    
    // default media shown is the first one
    this._currentMediaPos = 0;
    
    // search and set default position when a default media id is provided
    if(defaultMediaId = marker.data['DEFAULT_MEDIA_ID']) {
      for(var i=0; i < this._mediaCount; i++) {
        if(this._medias[i]['MED_ID'] == defaultMediaId) {
          this._currentMediaPos = i;
          break;
        }
      }
    }
    
    this.refresh();
    this._node.show();
  },
  
  refresh: function() {
    
    this.setArrowsDisplay();
    
    media = this._medias[this._currentMediaPos];
    this._mediaTitleNode.text(media['MED_TITLE']);
    
    this._preview.empty();

    //try {
      // load media function for each media type
      switch (media['MED_TYPE']) {
        
        case '1': // image
          this._preview.append('<div id="med-img"><img src="/uploads/usersfolders/' + this._marker.data['MAR_USER'] + '/m/' + media['MED_ID'] + '.'+ media['MED_FILE'] + '" alt="' + media['MED_TITLE'] + '" /></div>');
          break;
        
        case '2': // video
          this._preview.append('<div id="med-vid">' + media['MED_FILE'] + '</div>');
          break;
          
        case '3': // audio
          this._preview.append('<div id="med-aud"><p id="playeraudio"></p></div>');
          AudioPlayer.embed("playeraudio", {
            soundFile: "/uploads/usersfolders/" + this._marker.data['MAR_USER'] + "/" + media['MED_ID'] + ".mp3",
            titles: media['MED_TITLE'],
            autostart: "yes",
            transparentpagebg: "yes"
          });
          break;
        
        case '4': // text
          this._preview.append('<div id="med-txt">' + media['MED_TXT'] + '</div></div>');
          break;
          
        case '5': // rss
          this._preview.load(this._feedUrl, {feedId: media['MED_ID']});
          
          break;
      }
    //} catch(e) {}
  },
  
  hide: function() {
    this._node.hide();
  }
}


