IMapper = function() {
  var MAX_ZOOM = 15;
  var map = null;
  var bounds = new GLatLngBounds();
  var geocoder = new GClientGeocoder();
  
  var interval = null;
  var markers = {};
  var queue = [];
  
  var getPoint = function(location, args) {
    var caller = getPoint.caller
     if (typeof location == 'string') 
      geocoder.getLatLng(location, function(pt) {  if (pt) caller.apply(IMapper, [pt, args ? args : null]); });
    else if (location[0] && location[1]) 
      return new GLatLng(location[0], location[1]);
    else if (location.lat && location.lng)
      return location;
      
    return null;
  };
  
  var centerMap = function(center, zoom) {
    var point = getPoint(center, zoom);
    if (!point)
      return;
    map.setCenter(point, zoom > MAX_ZOOM ? MAX_ZOOM : zoom);
  };

  var eventHandler = function(ev) {
    if (!ev) return;
    
    if (ev.data)
      var id = ev.data['id'];
    else if (ev.openInfoWindow) 
      var id = ev.id;

    if (id) {
      var marker = markers[id].marker;
      var args = markers[id].args;
      var body = args['body'] ? args['body'] : (args['title'] ? args['title'] : args['id']);
      marker.openInfoWindow(body);
    }
  };  

  return {
    initialize: function(elem, center) {
      map = new GMap2(document.getElementById(elem));
      GEvent.addListener(map, "click", eventHandler);
      map.addControl(new GSmallMapControl());      
      centerMap(center, MAX_ZOOM);
      
      $("body").unload(function() { GUnload(); });
      return this;
    },
    
    addMarker: function(location, args) {
      if (!args['id'])
        return;
      
      var point = getPoint(location, args);
      if (!point)
        return;

      var id = args['id'];
      var marker = new GMarker(point, {title: args['title'], id:id});
      markers[id] = {marker:marker, args:args};
      
      queue.push(id);      
      if (interval == null && queue.length > 0)
        interval = setInterval("IMapper._build()", 500);
    },
    
    _build: function() {
      while (queue.length > 0) {
        var id = queue.pop();
        var marker = markers[id].marker;
        var args = markers[id].args;
        
        if (args['external']) 
          $(args['external']).bind('click', {id: id}, eventHandler);
        
        bounds.extend(marker.getLatLng());
        map.addOverlay(marker);
      }

      centerMap(bounds.getCenter(), map.getBoundsZoomLevel(bounds))
      
      if (queue.length == 0) {
        clearInterval(interval);
        interval = null;
      }
    }
  };
}();

// Relative only to Fiberon and Not IMapper
function getBody(elem){
  elem = $(elem);
  if (elem.html)
    return '<div class="map-marker-info">' + jQuery.trim(elem.html().replace(/<input [a-zA-Z0-9="_ ]+> /, '')) + '</div>';
  return "";
}

