/*
 * Fixed in cs/yui/connection.js
 * obj.responseText = o.conn.responseText.replace(/^\s*|\s*$/g,"");
 */

// map var
var map;
var mgr;
var restNameOverlay;
// default zoom level
var gmMinZoom = 11;
var gmDefZoom = 12;
var gmMaxZoom = 17;
// barTransportation toggle
var barToggle = 0;
// opens the marker if the name is set
var openNextMarker;
// sws marker manager types
var RESTAURANT = 0;
var LOCAL_EVENT = 1;
var PERSONAL_EVENT = 2;
var LOCATION = 3;

// restaurant icon
var goodRestaurantIcon = new GIcon();
	goodRestaurantIcon.image = "images/spoon-good.png";
	goodRestaurantIcon.shadow = "images/spoon-shadow.png";
	goodRestaurantIcon.iconSize = new GSize(22, 50);
	goodRestaurantIcon.shadowSize = new GSize(31, 46);
	goodRestaurantIcon.iconAnchor = new GPoint(5, 50);
	goodRestaurantIcon.infoWindowAnchor = new GPoint(14, 10);
var badRestaurantIcon = new GIcon();
	badRestaurantIcon.image = "images/spoon-bad.png";
	badRestaurantIcon.shadow = "images/spoon-shadow.png";
	badRestaurantIcon.iconSize = new GSize(22, 50);
	badRestaurantIcon.shadowSize = new GSize(31, 46);
	badRestaurantIcon.iconAnchor = new GPoint(5, 50);
	badRestaurantIcon.infoWindowAnchor = new GPoint(14, 10);
//var PersonalEventIcon = new GIcon();
//var LocalEventIcon = new GIcon();
//var LocationIcon = new GIcon();

//
// marked restaurants
var markedRestaurants = new Array();

//
//
//
function RestaurantNameOverlay(name, latlng) {
  this.name_ = name;
  this.latlng_ = latlng;
}
RestaurantNameOverlay.prototype = new GOverlay();

// Creates the DIV representing this RestaurantNameOverlay.
RestaurantNameOverlay.prototype.initialize = function(map) {
  // Create the DIV representing our rectangle
  var div = document.createElement("div");
  div.innerHTML = this.name_;
  div.style.width = "320px";
  div.style.fontSize = "80%";
  div.style.fontWeight = "bold";
  div.style.position = "absolute";
  div.style.display = "none";

  // Our rectangle is flat against the map, so we add our selves to the
  // MAP_PANE pane, which is at the same z-index as the map itself (i.e.,
  // below the marker shadows)
  map.getPane(G_MAP_FLOAT_PANE).appendChild(div);

  this.map_ = map;
  this.div_ = div;
}

// Remove the main DIV from the map pane
RestaurantNameOverlay.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
}

// Copy our data to a new Rectangle
RestaurantNameOverlay.prototype.copy = function() {
  return new RestaurantNameOverlay(this.name_, this.latlng_, this.backgroundColor_, this.opacity_);
}

// Redraw the rectangle based on the current projection and zoom level
RestaurantNameOverlay.prototype.redraw = function(force) {
  // We only need to redraw if the coordinate system has changed
  if (!force) return;
   
  // position this div
  var coord = this.map_.fromLatLngToDivPixel(this.latlng_);
  
  this.div_.style.top = coord.y + "px";
  this.div_.style.left = coord.x + "px";
  this.div_.innerHTML = this.name_;
  this.div_.style.display = "block";
}

/*
 * Creates and returns a new Restaurant Marker with the given information.
 */
function createRestaurantMarker(infos /*ARRAY: restaurant_id[s], latitude, longitude, name, excerpt, notice, score */) {
	var info = infos[0];
	var newMarker = new SWSMarker(info[0], new GMarker(new GLatLng(info[1], info[2]), (info[6] >= 60 ? goodRestaurantIcon : badRestaurantIcon)));
	
	var html = '';
	if (infos.length == 1) {
		// single restaurant case
		html = "<div class='marker'><a href='restaurant.php?id=" + info[0] + "'>" 
						+ info[3] + 
					"</a><div class='excerpt'>\"" 
						+ info[4] + 
					"\"</div><div class='notice'>" + 
					"<table cellpadding='0' cellspacing='0' width='100%'>" +
						"<tr>" +
							"<td width='20' align='center' style='font-size:.8em; font-weight: bold;'>" + info[6]  + "</td>" +
							"<td width='40' align='left' rowspan='2'><img style='margin-left: 5px;' src='";
						
		
		html += (info[6] >= 60) ? "images/goodSmall.png" : "images/nogoodSmall.png";
						
						
						
		html +=					"' /></td>" +
							"<td align='right' rowspan='2' valign='bottom'>" + createMoreInfoButton(info[0]) + "</td>" +
						"</tr>" +
						"<tr>" +
							"<td align='center' style='font-size: .7em; color: #999;'>score</td>" +
						"</tr>" +
					"</table>" +
					"</div></div>";					
	}else {
		// multi restaurant case
		html = "<div class='marker'>";
		
		for (var i = 0; i < infos.length; i++) {
			html += "<div class='notice'>" + 
						"<table cellpadding='0' cellspacing='0' width='100%'>" +
							"<tr>" +
								"<td width='20' align='center' style='font-size:.8em; font-weight: bold;'>" + infos[i][6]  + "</td>" +
								"<td width='40' align='left' rowspan='2'><img style='margin-left: 5px;' src='";
							
			
			html += (infos[i][6] >= 60) ? "images/goodSmall.png" : "images/nogoodSmall.png";
							
							
							
			html +=					"' /></td>" +
								"<td rowspan='2'><a href='restaurant.php?id=" + infos[i][0] + "'>" + infos[i][3] + "</a></td>" +						
							"</tr>" +
							"<tr>" +
								"<td align='center' style='font-size: .7em; color: #999;'>score</td>" +
							"</tr>" +
						"</table></div>";
			if (i < infos.length-1) {
				html += "<div style='border-bottom: 1px solid #ddd; padding-bottom: 10px;'></div>";
			}
		}
		html += "</div>";
	}
	
	newMarker.html = html;
		
	GEvent.addListener(newMarker.marker, "click", function(overlay, point) {
		map.closeInfoWindow();
		
		if (!overlay) {						
		// when the icon is clicked				
			newMarker.marker.openInfoWindowHtml(html);
			if (infos.length == 1) {
				addToRestaurantHistory(info[3]);
			}
		}
	});
	GEvent.addListener(newMarker.marker, "mouseover", function() {	   
		if (restNameOverlay) {
			map.removeOverlay(restNameOverlay);
			restNameOverlay = null; 
		}
		
		var names = '';
		for (var i = 0; i < infos.length; i++) {
			names += infos[i][3] + "<br/>";
		}
		restNameOverlay = new RestaurantNameOverlay(names, new GLatLng(info[1], info[2]));
		map.addOverlay(restNameOverlay);
		highlightLocation(parseFloat(info[1]), parseFloat(info[2]));
	});
	GEvent.addListener(newMarker.marker, "mouseout", function() {
		if (restNameOverlay) {
			map.removeOverlay(restNameOverlay);
			restNameOverlay = null;
			unhighlightLocation();
		}
	});
	
	return newMarker;
}

/*
 * Creates and returns a new Location Marker with the given information.
 */
function createLocationMarker(latitude, longitude) {
	var newMarker = new GMarker(new GLatLng(latitude, longitude));
	return newMarker;
}

/* 
 * Creates and returns a new Personal Event Marker with the given information.
 */
function createPersonalEventMarker(latitude, longitude) {
	var newMarker = new GMarker(new GLatLng(latitude, longitude));
	return newMarker;
}

/*
 * Creates and returns a new Local Event Marker with the given information.
 */
function createLocalEventMarker(latitude, longitude) {
	var newMarker = new GMarker(new GLatLng(latitude, longitude));
	return newMarker;
}

function SWSMarker(id, marker) {		
	// constructor vars
	this.id = id;
	this.marker = marker;
	this.html = '';
}

function SWSMarkerManager(m) {
	this.map = m;
	this.markers = new Array([], [], [], []); // each type has own array of markers
	
	/*
	 * Adds a specific marker to the manager.
	 */
	this.addAndShow = function(type, swsMarker) {
		// ensure that it does not already exist
		var marker = swsMarker;
		var found = false;
		for (var j = 0; j < this.markers[type].length && !found; j++) {
			var oldMarker = this.markers[type][j];
			if (swsMarker.id == oldMarker.id) {
				found = true;	
				marker = oldMarker;
			}
		}
		
		// if it does, skip, else add it to the array
		if (!found) {
			this.markers[type].push(swsMarker);
			this.map.addOverlay(swsMarker.marker);					
		}
		marker.marker.openInfoWindowHtml(marker.html);	
	}
	
	/*
	 * Add all new markers to the manager of a specific type.
	 */
	this.union = function(type, swsMarkers) {
		// for each incoming marker		
		for (var i = 0; i < swsMarkers.length; i++) {
			var newMarker = swsMarkers[i];
			
			// ensure that it does not already exist
			var found = false;
			for (var j = 0; j < this.markers[type].length && !found; j++) {				
				var oldMarker = this.markers[type][j];
				if (newMarker.id == oldMarker.id) {
					found = true;	
				}
			}
			
			// if it does, skip, else add it to the array
			if (!found) {
				this.markers[type].push(newMarker);
				this.map.addOverlay(newMarker.marker);
			}
		}
	}
		
	/*
	 * Removes all markers of a given type which dont have the given ids
	 */	 
	this.intersect = function(type, swsMarkers) {
		//remove all that are out of bounds
		var bounds = this.map.getBounds(); 
		var length = this.markers[type].length;
		var remCount = 0; 
		for (var i = 0; i < length; i++) {	
			var marker = this.markers[type][i-remCount].marker;	// gmarker
						
			if (!bounds.contains(marker.getPoint())) {
				map.removeOverlay(marker);
				this.markers[type].splice(i-remCount, 1);
				remCount++;
			}
		}		
		
		// remove all that are not in the new set
		// done after trimming bounding elements!
		length = this.markers[type].length;
		remCount = 0; 
		for (var i = 0; i < length; i++) {	
			var marker = this.markers[type][i-remCount];	// sws marker
						
			// check if this marker is in the new set
			var found = false;
			for (var j = 0; j < swsMarkers.length && !found; j++) {
				if (swsMarkers[j].id == marker.id) {
					found = true;
				}
			}
										
			if (!found) {
				map.removeOverlay(marker.marker);
				this.markers[type].splice(i-remCount, 1);
				remCount++;
			}			
		}	
				
		
		// add all the explicitly new ones
		this.union(type, swsMarkers);
	}
}

/*
 * Pans the map to the location of a specific restaurant iff it exists in our db.
 */
function moveToRestaurant(restaurantName) {	
	x_findRestaurant(restaurantName, panToCoordinate);
}	
function moveAndShowRestaurant(restaurantName) {
	// open the view
	x_findRestaurant(restaurantName, panToRestaurant);	
}
function panToRestaurant(result) {
	if (result.length > 0) {	
		var coordinate = result.split('\t');	
		
		openNextMarker = true;
		map.setCenter(new GLatLng(coordinate[1], coordinate[2]));		
		var marker = createRestaurantMarker(new Array(coordinate));
		mgr.addAndShow(RESTAURANT, marker);
		
		// now add it to history
		addToRestaurantHistory(coordinate[3]);		
	}
}


/*
 * Pans the map to a common or user location given the name and appropriate id.
 * Ids are disregarded for common locations.
 */
function moveToLocation(locationName) {
	x_findLocation(locationName, panToCoordinate);	
}
function panToCoordinate(result) {
	if (result.length > 0) {			
		var coordinate = result.split('\t');	
		
		if (coordinate[0].length > 15)
			document.getElementById('selectLocation').innerHTML = (coordinate[0].substring(0, 15) + "...");
		else
			document.getElementById('selectLocation').innerHTML = coordinate[0];
		map.setCenter(new GLatLng(coordinate[1], coordinate[2]), parseInt(coordinate[3]));
		updateZoomSlider();		
	}
}

/*
 * Zooms the map in if still within bounds
 */
function zoomIntoMap() {	
	var zoom = map.getZoom();
	if (zoom < gmMaxZoom) {
		map.zoomIn();
		updateZoomSlider();
		zoom++;
	}
	
	handleCurrentZoom(zoom);
}

/*
 * Handle zoom button state at max zoom.
 */
function handleCurrentZoom(zoom) {
	if (zoom == gmMaxZoom) {
		var label = document.getElementById('zoomlabel');
		label.src = 'images/zoomforarea.png';
		label.onclick = zoomOutOfMapCompletely;
	}else {
		var label = document.getElementById('zoomlabel');
		label.src = 'images/zoomforrestaurants.png';
		label.onclick = zoomIntoMap;
	}
}

/*
 * Zooms out of the map completely.
 */
function zoomOutOfMapCompletely() {
	map.setZoom(gmMinZoom);
	updateZoomSlider();
	
	handleCurrentZoom(map.getZoom());
}

/*
 * Zooms out of the map if still within bounds
 */
function zoomOutOfMap() {	
	if (map.getZoom() > gmMinZoom) {
		map.zoomOut();
		updateZoomSlider();
	}
	
	handleCurrentZoom(map.getZoom());
}

/*
 * Updates the view with all restaurants which are within bounds with the given filters.
 */
function updateRestaurantsInView() {	
	// get current bounds
	var bound = map.getBounds();
	var sw = bound.getSouthWest();
	var ne = bound.getNorthEast();
	
	// get the filter values		
	clearTopResults();
	/*
	alert("type: " + type);
	alert("kind: " + kind);
	alert("cost: " + cost);
	*/
	document.getElementById('loadingText').style.display = 'block';
	
	x_findRestaurantsWithinBounds(sw.lat(), sw.lng(), ne.lat(), ne.lng(), map.getZoom(), type, kind, cost, markRestaurantsInView);	
	var center = map.getCenter();
	setMapCookie(center.lat(), center.lng(), map.getZoom(), type, kind, cost);
}	

/* 
 * Marks all the restaurants which are within view.
 */
function markRestaurantsInView(result) {	
	var markers = new Array();
	markedRestaurants = new Array();
	
	document.getElementById('loadingText').style.display = 'none';
	//document.getElementById('debug_text').innerHTML = result;
		
	if (result.length > 0) {
		var coordinates = result.split('\n');
		
		// precompute all the overlapping coordinates
		for (var i = 0; i < coordinates.length; i++) {
			var coordinate = coordinates[i].split('\t');
			var coordStr = coordinate[1] + "" + coordinate[2];
			if (!markedRestaurants[coordStr]) {		
				markedRestaurants[coordStr] = new Array();				
			}
			markedRestaurants[coordStr].push(coordinate);
		}
		
		for (var i = 0; i < coordinates.length; i++) {
			if (coordinates[i].length > 0) {						
				var coordinate = coordinates[i].split('\t');	
				// if we overlay another one, then create with multiple names 
				var coordStr = coordinate[1] + "" + coordinate[2];
				marker = createRestaurantMarker(markedRestaurants[coordStr]);
				markers.push(marker);
			}
		}		
		
		// update top results
		var topResults = [];
		for (var i = 0; i < coordinates.length; i++) {
			if (coordinates[i].length > 0) {						
				var coordinate = coordinates[i].split('\t');		
				topResults.push([coordinate[3], coordinate[6], coordinate[0], coordinate[1], coordinate[2]]);
			}
		}				
		updateTopResults(topResults);
		updateNextTopResults = false;
	}
	mgr.intersect(RESTAURANT, markers);		
}

function addToRestaurantHistory(restaurantName) {	
	swf.call('addRestaurant', restaurantName, 'true');
}