/**
 * (C) 2008-2009 Marcello Barnaba <vjt@openssl.it>
 * http://sindro.me/
 */
/***/ (function($) {

// Private variables
var map, mgr;
var markers = {};
var Offsets, Sizes, Icons;

var center, bounds;
var zoom, zoom_min, zoom_max;
var configured = false;
var highlighted = {};

// Plugin entry point: initialize the Tmap
//
$.fn.tmap = function(options) {

  // Initialize Tmap
  if (!GBrowserIsCompatible()) {
    return this;
  }

  options = $.extend({}, options);
  if (!options.size) {
    options.size = new GSize(690, 224)
  }

  if (!configure(options)) {
    alert("Configuration failed (" + options + ")");
    return this;
  }

  map = new GMap2(this[0], {size: options.size});
  map.setCenter(center, zoom);
  map.savePosition();

  map.enableContinuousZoom();
  map.setMapType(G_SATELLITE_MAP);
  map.addControl(new GLargeMapControl());

  new GKeyboardHandler(map);

  setupMarkers();
  restrictZoom();
  restrictBounds();

  mgr = new MarkerManager(map);

  // Unload and cleanup Gmap
  $(window).unload(function() { GUnload(); });

  return this;
}

// API usage examples
//
$.fn.tmap_focusPlaceOnChange = function() {
  return this.each(function() {

    // The element needs to contain a value equal to the 
    // marker ID being shown
    $(this).bind('change', function() {
      $.tmap.focusMarker(this, 'places');
    });

  });
};

$.fn.tmap_reconfigureOnChange = function() {
  return this.each(function() {

    // The element needs to contain a JSON representation
    // of the map configuration in the "rel" attribute value.
    $(this).bind('change', function() {
      var config = $(this.options[this.selectedIndex]).attr('rel');
      $.tmap.reconfigure(window['eval']('(' + config + ')'));
    });

  });
}

// Public methods
//
$.tmap = function() {
  return map;
}

$.extend($.tmap, {
  reconfigure: function(options) {
    configure(options);
    map.setCenter(center, zoom);
    map.savePosition();
  },

  icons: function() {
    return Icons;
  },

  center: function() {
    return center;
  },

  focusMarker: function(element, type) {
    var id = $(element).val();
    if (id.length == 0) {
      if (map.infobox) {
        map.removeOverlay(map.infobox);
      }
      map.panTo(center);
    } else {
      GEvent.trigger(markers[type][id].ovl, 'click');
    }
  },

  highlightMarker: function(id, type) {
    highlighted = {id: id, type: type};
  },

  addMarkers: function(points, type) {
    window.setTimeout(function() { 

    markers[type] = points;

    var ary = [];
    for (var id in points) {
      var m = points[id];
      var point = new GLatLng(m.lat, m.lng);
      var current = type + '-current';

      if (highlighted.type == type && highlighted.id == id) {
        // CURRENT marker, small infobox, no click handler
        m.ovl = new GMarker(point, {icon: Icons[current], clickable: false});

        var current = new InfoBox(point, {
          content: ' ', className: 'current infobox ' + type, close: false,
          offsetHorizontal: Offsets[current].x,
          offsetVertical: Offsets[current].y,
          width: Sizes[current].x,
          height: Sizes[current].y
        });
        map.setCenter(point);
        map.addOverlay(current);

      } else {
        // OTHER marker, full infobox, click handler
        m.ovl = new GMarker(point, {icon: Icons[type], clickable: true});

        m.ovl.infobox = new InfoBox(point, {
          content: m.html, className: 'infobox ' + type, close: true,
          offsetHorizontal: Offsets[type].x,
          offsetVertical: Offsets[type].y,
          width: Sizes[type].x,
          height: Sizes[type].y
        });

        GEvent.addListener(m.ovl, 'click', function() {
          if (map.infobox) {
            map.removeOverlay(map.infobox);
          }
          map.infobox = this.infobox;
          map.addOverlay(map.infobox);
        });

      }
      
      ary.push(m.ovl);
    }

    /*GEvent.addListener(map, 'click', function(marker) {
      if (marker == null && map.infobox) {
        map.removeOverlay(map.infobox);
        map.infobox = null;
      }
    });*/

    mgr.addMarkers(ary, zoom_min);

    }, 0); // setTimeout
  },

  refresh: function() {
    window.setTimeout(function() { mgr.refresh() }, 1);
  }
});

// Private methods
// 
function configure(options) {
  if (!(options.center && options.bounds && options.zoom)) {
    return false;
  }

  center = new GLatLng(options.center[0], options.center[1]);
  bounds = new GLatLngBounds(
    new GLatLng(center.lat() - options.bounds.ne[0], center.lng() - options.bounds.ne[1]),
    new GLatLng(center.lat() + options.bounds.sw[0], center.lng() + options.bounds.sw[1])
  );
  zoom     = options.zoom.def;
  zoom_min = options.zoom.min;
  zoom_max = options.zoom.max;

  configured = true;
  return true;
}

function setupMarkers() {
  var icon;
  Icons = {};

  icon = new GIcon();
  icon.image = '/images/map/blue-placemark.png';
  icon.iconSize = new GSize(20, 28);
  icon.shadow = '/images/map/blue-shadow.png';
  icon.shadowSize = new GSize(30, 28);
  icon.iconAnchor = new GPoint(0, 28);
  Icons['places'] = icon;

  icon = new GIcon(icon);
  icon.image = '/images/map/blue-placemark-current.png';
  Icons['places-current'] = icon;

  icon = new GIcon();
  icon.image = '/images/map/yellow-placemark.png';
  icon.iconSize = new GSize(14, 14);
  icon.shadow = '';
  icon.shadowSize = new GSize(1, 1);
  icon.iconAnchor = new GPoint(7, 6);
  Icons['businesses'] = icon;

  icon = new GIcon(icon)
  icon.image = '/images/map/yellow-placemark-current.png';
  Icons['businesses-current'] = icon;

  Offsets = {
    'places':             { x: 0,   y: -110 },
    'places-current':     { x: 10,  y: -51 },
    'businesses':         { x: -10, y: -94 },
    'businesses-current': { x: -3,  y: -30 }
  };

  Sizes = {
    'places':             { x: 274, y: 94 },
    'places-current':     { x: 55,  y: 29 },
    'businesses':         { x: 274, y: 94 },
    'businesses-current': { x: 73,  y: 29 }
  };
}

// This Javascript is based on code provided by the Blackpool Community Church Javascript Team
// http://www.commchurch.freeserve.co.uk/ ~ http://econym.googlepages.com/index.htm
//
// The allowed region which the whole map must be within. If the map position is out of range,
// move it back
function checkBounds() {
  // Perform the check and return if OK
  if (bounds.contains(map.getCenter())) {
    return;
  }

  // It`s not OK, so find the nearest allowed point and move there
  var C = map.getCenter();
  var X = C.lng();
  var Y = C.lat();

  var AmaxX = bounds.getNorthEast().lng();
  var AmaxY = bounds.getNorthEast().lat();
  var AminX = bounds.getSouthWest().lng();
  var AminY = bounds.getSouthWest().lat();

  if (X < AminX) {X = AminX;}
  if (X > AmaxX) {X = AmaxX;}
  if (Y < AminY) {Y = AminY;}
  if (Y > AmaxY) {Y = AmaxY;}

  map.setCenter(new GLatLng(Y,X));
}

function restrictBounds() {
  GEvent.addListener(map, "move", checkBounds);
}

function restrictZoom() {
  if (!zoom) return;

  // ====== Restricting the range of Zoom Levels =====
  // Get the list of map types      
  var mt = map.getMapTypes();

  // Overwrite the getMinimumResolution() and getMaximumResolution() methods
  for (var i=0; i<mt.length; i++) {
    mt[i].getMinimumResolution = function() {return zoom_min;}
    mt[i].getMaximumResolution = function() {return zoom_max;}
  }
}
// Blackpool code ends here

/***/ })(jQuery);
