/*
 * jMapping v1.1 - jQuery plugin for creating Google Maps
 * 
 * Copyright (c) 2009 Brian Landau (Viget Labs)
 * MIT License: http://www.opensource.org/licenses/mit-license.php
 *
 * geolocator added by Daantje.nl and i-v-o.nl
 */

if (GMap2){
  GMap2.prototype.centerAndZoomOnBounds = function(bounds) {
    this.setCenter(bounds.getCenter(), this.getBoundsZoomLevel(bounds));
  };
}

function is_object( mixed_var ){  
    // Returns true if variable is an object    
    //   
    // version: 810.114  
    // discuss at: http://phpjs.org/functions/is_object  
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)  
    // +   improved by: Legaev Andrey  
    // +   improved by: Michael White (http://getsprink.com)  
    // *     example 1: is_object('23');  
    // *     returns 1: false  
    // *     example 2: is_object({foo: 'bar'});  
    // *     returns 2: true  
    // *     example 3: is_object(null);  
    // *     returns 3: false  
    if(mixed_var instanceof Array) {  
        return false;  
    } else {  
        return (mixed_var !== null) && (typeof( mixed_var ) == 'object');  
    }  
}  

(function($){
  $.jMapping = function(map_elm, options){
    this.map_elm = (typeof map_elm == "string") ? $(map_elm).get(0) : map_elm;
    
    if (!($(this.map_elm).data('jMapping') instanceof $.jMapping)){
      this.settings = $.extend(true, {}, $.jMapping.defaults);
      $.extend(true, this.settings, options);
      
      if (GBrowserIsCompatible()) {
        this.init();
      } else {
        this.mapped = false;
      }
    }
  };
  
  $.extend($.jMapping, {
    defaults: {
      side_bar_selector: '#map-side-bar:first',
      location_selector: '.map-location',
      link_selector: 'a.map-link',
      info_window_selector: '.info-box',
      info_window_max_width: 425,
      metadata_options: {type: 'attr', name: 'data'}
    },
	geoCode: function(a, callBack){
		geocoder = new GClientGeocoder();
		geocoder.getLocations(a.address, function(response){
			if(response.Status.code == 200){
				lon = response.Placemark[0].Point.coordinates[0];
				lat = response.Placemark[0].Point.coordinates[1];
				a.point=  {'lat': lat, 'lng': lon};
				callBack(new GLatLng(lat, lon));
			}
		});
	},

    makeGLatLng: function(place_point,callBack){
		if (!callBack) callBack = function(){};
		if(is_object(place_point)){
		  if(!is_object(place_point.point)){
			  this.geoCode(place_point, callBack);
		  }else{
			  callBack(new GLatLng(place_point.point.lat, place_point.point.lng));
		  }
		}
	}
  });
  
  $.jMapping.prototype = {
    gmarkers: {},
    mapped: true,
    hasMap : false,
    init: function(update){
      var self = this, places, info_window_selector, bounds;
      info_window_selector = [
        this.settings.side_bar_selector, 
        this.settings.location_selector, 
        this.settings.info_window_selector
      ].join(' ');
      $(info_window_selector).hide();
      places = this.getPlaces();

      var places_data = this._getPlacesData(places);

	$.jMapping.makeGLatLng(places_data[0], function(latLng){
		var bounds = new GLatLngBounds(latLng, latLng);
		for (var i=0, len = places_data.length ; i<len; i++) {
			$.jMapping.makeGLatLng(places_data[i], function(latLngToo){
				bounds.extend(latLngToo)
			})
			if (!self.hasMap){
				self.createMap(places, bounds);
				self.markerManager = new MarkerManager(self.map);
				self.gmarkers = {};
				self.hasMap = true;
			}

			places.each(function(){
				self._createMarker(this, function(marker){
					bounds_zoom_level = self.map.getBoundsZoomLevel(bounds);
					min_zoom = (bounds_zoom_level < 7) ? 0 : (bounds_zoom_level - 7);
	
					self.markerManager.addMarkers(self._gmarkersArray(), min_zoom);
				});
				self.markerManager.refresh();
				self.map.centerAndZoomOnBounds(bounds);
			});

	      
			if (!(self.settings.link_selector === false) && !update){
				self._attachMapsEventToLinks();
	      		}
		}

	})
    },
    update: function(){
      this.init(true);
    },
    createMap: function(places, bounds){
      this.map = new GMap2(this.map_elm);
      if ($.isFunction(this.settings.map_config)){
        this.settings.map_config.apply(this, [this.map]);
      } else {
        this.map.setMapType(G_NORMAL_MAP);
        this.map.addControl(new GSmallMapControl());
      }
      this.map.centerAndZoomOnBounds(bounds);
    },
    getPlaces: function(){
      return $(this.settings.side_bar_selector+' '+this.settings.location_selector);
    },
    _getPlacesData: function(places){
      var self = this;
      return places.map(function(){
        return $(this).metadata(self.settings.metadata_options);
      });
    },
    _getBounds: function(places, callBack){
      var places_data = this._getPlacesData(places);
	$.jMapping.makeGLatLng(places_data[0], function(latLng){
		var bounds = new GLatLngBounds(latLng, latLng);
		for (var i=0, len = places_data.length ; i<len; i++) {
			$.jMapping.makeGLatLng(places_data[i], function(latLngToo){
				bounds.extend(latLngToo)
			})
			callBack(bounds);
		}

	})
    },
    _setupLink: function(place_elm){
      var $place_elm = $(place_elm);
      var location_data = $place_elm.metadata(this.settings.metadata_options);
      var link = $place_elm.find(this.settings.link_selector);
      
      if (link.attr('href').match(/^((\#.*)|(\s*))$/)){
        link.attr('href', ("#" + location_data.id));
      }
    },
    _chooseIconOptions: function(category){
      if (this.settings.category_icon_options){
        if ($.isFunction(this.settings.category_icon_options)){
          return this.settings.category_icon_options.apply(this, [category]);
        } else {
          return this.settings.category_icon_options[category] || this.settings.category_icon_options['default'];
        }
      } else {
        return {};
      }
    },
    _createMarker: function(place_elm, callBack){
      var place_data, point, marker, $info_window_elm;
      var self = this
      
      place_data = $(place_elm).metadata(this.settings.metadata_options);
      $.jMapping.makeGLatLng(place_data, function(latLng){
	      if (self.settings.category_icon_options){
		var custom_icon = MapIconMaker.createMarkerIcon(self._chooseIconOptions(place_data.category));
		marker = new GMarker(latLng, {icon: custom_icon});
	      } else {
		marker = new GMarker(latLng);
	      }
	      $info_window_elm = $(place_elm).find(self.settings.info_window_selector);
	      if ($info_window_elm.length > 0){
		marker.bindInfoWindowHtml(
		  $info_window_elm.html(), 
		  {maxWidth: self.settings.info_window_max_width}
		);
	      }

	      self.gmarkers[parseInt(place_data.id, 10)] = marker;
		if (!(self.settings.link_selector === false)){
	  		self._setupLink(place_elm);
		}
		callBack(marker);
	});
    },
    _attachMapsEventToLinks: function(){
      var self = this;
      var location_link_selector = [
        this.settings.side_bar_selector, 
        this.settings.location_selector, 
        this.settings.link_selector
      ].join(' ');
      $(location_link_selector).live('click', function(e){
        e.preventDefault();
        var marker_index = parseInt($(this).attr('href').split('#')[1], 10);
        GEvent.trigger(self.gmarkers[marker_index], "click");
      });
    },
    _gmarkersArray: function(){
      var marker_arr = [];
      $.each(this.gmarkers, function(key, value){
        marker_arr.push(value);
      });
      return marker_arr;
    }
  };
  
  $.fn.jMapping = function(options){
    if ((options == 'update') && $(this[0]).data('jMapping')){
      $(this[0]).data('jMapping').update();
    } else {
      if (options == 'update') options = {};
      $(this[0]).data('jMapping', new $.jMapping(this[0], options));
    }
    return this;
  };
})(jQuery);

