/**
* Wimgo Maps Library
*
* Follows the Javascript module pattern:
* @link http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
*/

var wimgo = wimgo || {};
wimgo.geo = wimgo.geo || {};
wimgo.maps = (function (wimgo, $, google) {
	var t = {}; // Return object that will expose public methods
	// Global options for maps and plotted points
	t.options = {
		itemLimit: 500, // Items PER TYPE (events, movies, etc)
		zoom: 13, // Google map zoom level
		refreshDistance: 10, // Minimum km to move map before it pulls in more data from the API
		streetViewControl: false
	};
	
	
	/**
	 * PROTECTED methods - NOT exposed to the public
	 */
	var p = {};
	p.dataType = null;
	p.pointMarkers = {};
	p.pointInfo = {};
    p.homeCenter = null;
	p.mapCenter = null;
	p.mapRefreshTimeout = null;
    // Shared infoWindow object between all markers (faster/more efficient than markers for each)
    p.infoWindow = new google.maps.InfoWindow();
	
	// Draw controls for marker toggle
	p.drawMarkerToggleControls = function(map) {
		// Default button styles
		var btnStyles = {
			'display': 'block',
			'margin-left': '23px',
			'font-size': '11px',
			'cursor': 'hand',
			'width': '21px',
			'height': '21px',
			'text-indent': '-9999px'
		};
		
		// Buttons
		var btn = new Object();
		btn['restaurant'] = $('<div/>')
			.attr({
				'id': 'map_btn_toggle_restaurant',
				'class': 'map_btn_toggle'
			})
			.text("Restaurants")
			.css(btnStyles)
			.addClass('map_toggle_restaurants map_toggle_active')
			.click(function() {
				t.refreshMap('restaurant');
				$(this).addClass('map_toggle_active').siblings().removeClass('map_toggle_active');
			});
		btn['event'] = $('<div/>')
			.attr({
				'id': 'map_btn_toggle_event',
				'class': 'map_btn_toggle'
			})
			.text("Events")
			.css(btnStyles)
			.addClass('map_toggle_events')
			.click(function() {
				t.refreshMap('event');
				$(this).addClass('map_toggle_active').siblings().removeClass('map_toggle_active');
			});
		btn['theatre'] = $('<div/>')
			.attr({
				'id': 'map_btn_toggle_theatre',
				'class': 'map_btn_toggle'
			})
			.text("Theatres")
			.css(btnStyles)
			.addClass('map_toggle_theatres')
			.click(function() {
				t.refreshMap('theatre');
				$(this).addClass('map_toggle_active').siblings().removeClass('map_toggle_active');
			});
        // HOME
        btn['home'] = $('<div/>')
			.attr({
				'id': 'map_btn_home',
				'class': 'map_btn'
			})
			.text("Home")
			.click(function() {
				t.gmap.setCenter(p.homeCenter);
                t.refreshMap();
			});
		
		// Add controls to map
		for(btnType in btn) {
			t.gmap.controls[google.maps.ControlPosition.LEFT].push(btn[btnType].get(0));
		}
	};
	// Place markers on the map
	p.placeMarkersByType = function(type, o, items) {
		p.pointMarkers = new Array(items.length);
		p.pointInfo = new Array(items.length);
	   
		// Marker icon
		var markerIcon;
		switch(type) {
			case 'event':
                markerIcon = new google.maps.MarkerImage('http://s3.amazonaws.com/wimgo/images/map_icons/mapicon2_o_5.png',
                    // This marker is 21 pixels wide by 25 pixels tall.
                    new google.maps.Size(21, 25),
                    // The origin for this image is 0,0.
                    new google.maps.Point(0,0),
                    // The anchor for this image
                    new google.maps.Point(0, 0));
			break;
			case 'theatre':
                markerIcon = new google.maps.MarkerImage('http://s3.amazonaws.com/wimgo/images/map_icons/mapicon2_o_4.png',
                    // This marker is 21 pixels wide by 25 pixels tall.
                    new google.maps.Size(21, 25),
                    // The origin for this image is 0,0.
                    new google.maps.Point(0,0),
                    // The anchor for this image
                    new google.maps.Point(0, 0));
			break;
			case 'restaurant':
                markerIcon = new google.maps.MarkerImage('http://s3.amazonaws.com/wimgo/images/map_icons/mapicon2_o_1.png',
                    // This marker is 21 pixels wide by 25 pixels tall.
                    new google.maps.Size(21, 25),
                    // The origin for this image is 0,0.
                    new google.maps.Point(0,0),
                    // The anchor for this image
                    new google.maps.Point(0, 0));
			break;
		}
		
		$.each(items, function(i,item) {
			// Add point to map
			var venue = item.venue || item;
			var itemTitle = venue.title || venue.name;
			var itemId = item.id || item.venueId;
			p.pointMarkers[itemId] = new google.maps.Marker({
				position: new google.maps.LatLng(venue.latitude, venue.longitude),
				title: itemTitle,
				icon: markerIcon
			});
			// Click event
			var infoContent = t.markerInfoContent(item, type);
			google.maps.event.addListener(p.pointMarkers[itemId], 'click', function() {
              t.openInfoWindow(p.pointMarkers[itemId], infoContent);
			});
			// Add marker to Fluster2 for clustering
			p.fluster.addMarker(p.pointMarkers[itemId]);
		});
		
		p.fluster.initialize();
	};
	// Clear all markers on map
    p.clearAllMarkers = function() {
		for(i in p.pointMarkers) {
		   // Clear marker by setting map to NULL
		   if(typeof(p.pointMarkers[i]) == "object" && typeof(p.pointMarkers[i]['setMap']) == "function") {
			   p.pointMarkers[i].setMap(null);
		   }
		}
		// Empty variables
		p.pointMarkers = {};
		p.pointInfo = {};
    };
	// Plot event points
	p.plotEvents = function(o) {
		var o = o || {};
		$.extend(o, t.options);
	//	$.getJSON("http://"+window.wimgo_api_host+"/2.0/events.json?limited=1&longitude="+o.longitude+"&latitude="+o.latitude+"&distance="+wimgo.geo.radius+"&count="+o.itemLimit+"&page=1&callback=?", function(data) {
		$.getJSON("http://"+window.wimgo_api_host+"/2.0/events.json?limited=1&nw_point="+o.nw_point+"&se_point="+o.se_point+"&longitude="+o.longitude+"&latitude="+o.latitude+"&count="+o.itemLimit+"&page=1&callback=?", function(data) {
			p.placeMarkersByType('event', o, data.events);
		});
	};
	// Plot movie theatre points
	p.plotTheatres = function(o) {
		var o = o || {};
		$.extend(o, t.options);
		$.getJSON("http://"+window.wimgo_api_host+"/2.0/movies/theaters.json?limited=1&nw_point="+o.nw_point+"&se_point="+o.se_point+"&longitude="+o.longitude+"&latitude="+o.latitude+"&count="+o.itemLimit+"&page=1&callback=?", function(data) {
			p.placeMarkersByType('theatre', o, data.theaters);
		});
	};
	// Plot restaurant points
	p.plotRestaurants = function(o) {
		var o = o || {};
		$.extend(o, t.options);
		$.getJSON("http://"+window.wimgo_api_host+"/2.0/restaurants.json?limited=1&nw_point="+o.nw_point+"&se_point="+o.se_point+"&longitude="+o.longitude+"&latitude="+o.latitude+"&count="+o.itemLimit+"&page=1&callback=?", function(data) {
			p.placeMarkersByType('restaurant', o, data.restaurants);
			$(".map-loading").remove();
		});
	};
	
	
	/**
	 * PUBLIC methods
	 */
	// Initialize and place map
	t.init = function(dataType) {

		// Determine default data type and save it
		var dataType = dataType || "restaurant";
		t.setDataType(dataType);
		
        // Save first set center as home
        p.homeCenter = new google.maps.LatLng(wimgo.geo.latitude, wimgo.geo.longitude);
        
        // Init map
		t.gmap = new google.maps.Map(document.getElementById("home-map"), {
			zoom: t.options.zoom,
    		scrollwheel: false,
			center: p.homeCenter,
			mapTypeId: google.maps.MapTypeId.ROADMAP,
			mapTypeControl: false,
			mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
			navigationControl: false,
			streetViewControl: false
		});
		// Add custom controler overlay
		t.gmap.controls[google.maps.ControlPosition.TOP_LEFT].push(new missouristate.web.ZoomPanControl(t.gmap));
		
		// Initialize Fluster2
		p.fluster = new Fluster2(t.gmap, false);
		
        // Make the info window close when clicking anywhere on the map.
        google.maps.event.addListener(t.gmap, 'click', t.closeInfoWindow);
        
		// Notify when map center changes ('center_changed', 'zoom_changed' or 'dragend')
		google.maps.event.addListener(t.gmap, 'idle', t.refreshMap);
	    google.maps.event.addListener(t.gmap, 'zoom_changed', t.refreshMap);
		google.maps.event.addListener(t.gmap, 'dragend', t.refreshMap);
		
		// Toggle marker visibility
		p.drawMarkerToggleControls(t.gmap);
	};
	// Set current data type for markers
	t.setDataType = function(dataType) {
		p.dataType = dataType;
	};
	// Marker Info window HTML
	t.markerInfoContent = function(item, type) {
		var venue = item.venue || item;
		var itemTitle = venue.title || venue.name;
        if(item.url) {
		    var itemUrl = item.url;
        } else {
            if( type == 'event' ) {
                var itemUrl = 'http://wimgo.com/events/' + item.eventId;
            } else {
                var itemUrl = 'http://wimgo.com/business/' + item.venueId;
            }
        }
		if(type == 'theatre') {
			itemUrl = 'http://wimgo.com/business/' + item.venue_id;
		}
		var content = "<div><b><a class='color1 hdr-font' href='" + itemUrl + "'>" + itemTitle + "</a></b>";
		if(venue.address1) {
			content += "<br/>" + venue.address1;
		}
		if(venue.address2) {
			content +=  "<br/>" + venue.address2;
		}
		if(venue.city && venue.state) {
			content += "<br/>" + venue.city + ", "+venue.state;
		}
        content += '</div>';
		return content;
	};
	// Open/close infowindow bubble popups
    t.closeInfoWindow = function() {
        p.infoWindow.close();
    };
    t.openInfoWindow = function(marker, content) {
        var markerLatLng = marker.getPosition();
        p.infoWindow.setContent(content);
        p.infoWindow.open(t.gmap, marker);
    };
	// Callback for map move - determines if maps needs refresh or not
	t.moveMap = function() {
		// Clear any previously set refresh timeout
		window.clearInterval(p.mapRefreshTimeout);

        p.infoWindow.close();

		// See if map has been moved far enough away to justify a recalculation
		if(null !== p.mapCenter) {
			var distance = p.mapCenter.distanceFrom(t.gmap.getCenter()); // in km
			
			if(distance > t.options.refreshDistance) {
				// Set timeout to refresh map
				p.mapRefreshTimeout = window.setTimeout(t.refreshMap, 500);
			}
		}
	};
	// Plot markers by type
	t.refreshMap = function(type) {
		$(".map-wide").prepend('<div class="mod basic map-loading hdr-font"><div class="inner bg-color10 color9"><img src="http://s3.amazonaws.com/wimgo/images/map_icons/loading-graphic-icon.png">loading new spots</div></div>');
		var loadedStatus = "yes";
		
        google.maps.event.clearListeners(t.gmap, 'idle');
		// Clear previous points / data
		p.fluster.reset();
		//p.clearAllMarkers();
		
		// Plot new points
		var o = wimgo.geo;
		
		// Set lat/lon based on new map center
		var mapCenter = t.gmap.getCenter();
		o.latitude = mapCenter.lat();
		o.longitude = mapCenter.lng();
        o.nw_point = t.gmap.getBounds().getNorthEast().lat() + ',' + t.gmap.getBounds().getSouthWest().lng();
        o.se_point = t.gmap.getBounds().getSouthWest().lat() + ',' + t.gmap.getBounds().getNorthEast().lng();
		
		// Save map center as last center refreshed from
		p.mapCenter = mapCenter;
		
		var type = type || p.dataType;
		switch(type) {
			case 'event':
				p.plotEvents(o);
			break;
			case 'theatre':
				p.plotTheatres(o);
			break;
			case 'restaurant':
				p.plotRestaurants(o);
			break;
		}
		
		// Display clusters
		//p.fluster.initialize();
	};
	
	// Return public object as "exposed" interface
	return t; 
}(wimgo, jQuery, google));




	isMapLoaded = 0;
function mapWimgoOptions() {
	// Map Options for jQuery UI
	$( ".map-wide" ).resizable({ handles: 's' },{ minHeight: 200 },{ maxHeight: 450 });
	$( ".map-wide" ).resizable( "option", "handles", 's', "minHeight", 200, "maxHeight", 450 );
	mapTop = $(".header").height();
	$(".map-wide").before("<div class='map-toggle map-toggle-shadow' style='top: "+mapTop+"px'><i class='color3'>&#9660;</i> Show Map</div>");
	$(".map-wide").prepend(	"<div class='home-spotlight-shadow map-wide-shadow'></div>"+
											"<div class='map-wide-shadow-n map-wide-shadow'></div>"+
											"<div class='map-wide-shadow-s map-wide-shadow'></div>"+
											"<div class='map-wide-shadow-e map-wide-shadow'></div>"+
											"<div class='map-wide-shadow-w map-wide-shadow'></div>"
	);
	$('.home-spotlight-shadow').animate({ bottom: "-20px" }, 500);
	$(".map-toggle").toggle(function(){
			// Show Map
			if ( $('.home-spotlight-shadow').length > 0 ) {
				$('.home-spotlight-shadow').animate({ top: "+=260px" }, 900);
			}
			$('.map-wide').animate({ height: "300px" }, 1000, function() {
					if ( isMapLoaded == 0 ) {
						// Load map
						wimgo.maps.init('restaurant');
						//wimgo.maps.refreshMap();
						isMapLoaded = 1;
						$(".map-wide").prepend(	"<div class='home-spotlight-shadow map-wide-shadow'></div>"+
																"<div class='map-wide-shadow-n map-wide-shadow'></div>"+
																"<div class='map-wide-shadow-s map-wide-shadow'></div>"+
																"<div class='map-wide-shadow-e map-wide-shadow'></div>"+
																"<div class='map-wide-shadow-w map-wide-shadow'></div>"
						);	
					}
			});
			$('#content_main').animate({ marginTop: "-50px" }, 1000);
			$('.billboard').slideUp(1000);
			$(".map-toggle").html("<i class='color3'>&#9650;</i> Hide Map");	
			return false;
	},function(){
		// Hide Map
			$('.map-wide').animate({ height: "0px" }, 1000);
			$('#content_main').animate({ marginTop: "10px" }, 1000);
			$('.home-spotlight-shadow').animate({ top: "0" }, 1100);
			$(this).html("<i class='color3'>&#9660;</i> Show Map");
			return false;
	});
}

// note: to support IE (anger rising as I type), you'll need this (thanks James!):
// @link http://briancray.com/2009/09/30/remove-value-javascript-array/
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(elt /*, from*/) {
    var len = this.length >>> 0;
 
    var from = Number(arguments[1]) || 0;
    from = (from < 0)
         ? Math.ceil(from)
         : Math.floor(from);
    if (from < 0)
      from += len;
 
    for (; from < len; from++) {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}


/**
 * Calculates the distance between two latlng locations in km.
 * @see http://www.movable-type.co.uk/scripts/latlong.html
 *
 * @param {google.maps.LatLng} p2 The second lat lng point.
 * @return {number} The distance between the two points in km.
*/
google.maps.LatLng.prototype.distanceFrom = function(p2) {
	if (!p2) {
	  return 0;
	}
	var p1 = this;
	
	var R = 6371; // Radius of the Earth in km
	//var R = 6371000; // meters 
	var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
	var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
	var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
	  Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
	  Math.sin(dLon / 2) * Math.sin(dLon / 2);
	var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
	var d = R * c;
	return d;
};

