// foodtyrant.js 2: by Matt Demanett for Substantial LLC, Fangohr LLC
// Copyright 2008 FoodTyrant.com

/// Utils
var _debug = true;

function log(msg) {
    if (_debug) {
		if (Prototype.Browser.Gecko)
            window.setTimeout(function() { throw msg; }, 1);
		else if (Prototype.Browser.WebKit) 
		    console.log(msg);
    }
}
try { console.assert(1); } catch(e) { console = { log: function() {}, assert: function() {}, debug: function() {} } }
/// Popup class.

function FTPopup(marker) {
    this.marker = marker;
}

function FTPopupInit() {

	FTPopup.prototype = new google.maps.Overlay();

	FTPopup.prototype.initialize = function(map) {
	    this.div = $(document.createElement('div'));
	    this.div.className = 'ftinfowindow';
	    this.div.style.position = 'absolute';
	    //this.div.observe('click', function() { _ft.hidePopup(); });
	    this.div.hide();
	
	    this.divStem = $(document.createElement('div'));
	    this.divStem.style.position = 'absolute';
	    this.divStem.style.height = '11px';
	    //this.divStem.observe('click', function() { _ft.hidePopup(); });
	    this.divStem.update('<img src="/img/info_stem.png" width="242" height="9" />');
	    this.divStem.hide();
	
	    map.getPane(G_MAP_FLOAT_PANE).appendChild(this.div);
	    map.getPane(G_MAP_FLOAT_PANE).appendChild(this.divStem);
	    this.map = map;
	}
	
	FTPopup.prototype.remove = function() {
	    this.div.parentNode.removeChild(this.div);
	    this.divStem.parentNode.removeChild(this.divStem);
	}
	
	FTPopup.prototype.copy = function() {
	    return new FTPopup(this.marker);
	}
	
	FTPopup.prototype.setMarker = function(marker) {
	    this.marker = marker;
	    this.redraw(true);
	}
	
	FTPopup.prototype.hide = function() {
	    this.div.hide();
	    this.divStem.hide();
	}

	FTPopup.prototype.redraw = function(force) {
	    if (!force || !this.marker) return;
	
	    this.div.update(this.marker.html);
	    
	    this.div.select('a.ftinfowindow-link').each(function(el) {
			el.observe('click', function(event) { 
/*
			    _ft.addHashToLink(el);
			    _ft.setState(el.href); 
*/
				event.preventDefault();
				$j.address.value($j(this).attr('href'));
			    
			    //the following line prevents the 'View Details...' button from changing the URL
			    //event.stop();
			});
	    });
	
	    var p = this.map.fromLatLngToDivPixel(this.marker.point);
	    this.div.style.left = p.x + 'px';
	    this.div.style.bottom = (-p.y + 11 - 2) + 'px';
	    this.divStem.style.left = (p.x + 1) + 'px';
	    this.divStem.style.bottom = (-p.y - 2) + 'px';
	
	    this.div.show();
	    this.divStem.show();
	}
} // end FTPopupInit()

// Global holder for the main page state.

var _ft = {
    marker_on_image: '/img/marker_on.png',
    marker_off_image: '/img/marker_off.png',

    map: null,
    markers: [],
    markers_by_id: {},    

    loading: false,
    cache: {},
    preloadImages: [],

    iphone: navigator.userAgent.toLowerCase().indexOf("iphone") > -1,

    // Update the page to a particular state, based on /#/foo/bar links.
    // Now called in $j.address.change()
    
//    setState: function(url) {
    setState: function() {
    	console.log('setstate');
		if (this.loading) {
			return;
		}
		
		var site = 'http://' + window.location.hostname;
		var url = $j.address.value();
		//var params = /^(?:http:\/\/.*?)?(?:\/#)?\/(\w+)\/(view)\/(\d+)[^\/]*\/?(.*)?$/.exec(url) || [];
		var params = $j.address.pathNames();
		var baseurl = $j.address.baseURL(); 
		var baseurl_split = baseurl.split(site);
		
		//if we're on a non-dynamic page, redirect to a dynamic page.
		//ie., http://foodtyrant.com/venues/view/132_fb_gudtfood/sort:nosort --> http://foodtyrant.com/#/venues/view/132_fb_gudtfood/sort:nosort
		console.log(baseurl_split[1]);
		console.log(url);
		if(baseurl_split[1] != '') {
			window.location = site + '/#' + url;
			return;
		}
		
		if(params != '') {
			var controller = params[0];
			var action = params[1];
			var id = params[2];
			var extra = params[3];
						
			if (controller == 'areas') {
			    if (extra && !extra.match(/^(nosort|price|style|type)/))
				extra = 'nosort/' + extra;
			    this.loading = true;

			    this.runMarkersUpdate(id);
			    
			    (function () {
			    	_ft.runAreaUpdate(id, extra);
			    }).delay(.001);
	        } else if (controller == 'venues') {
			    this.loading = true;
			    this.runVenueUpdate(id, extra);
			} else {
			    log('unknown state URL: "' + url + '"');
			}
			
		}
    },

    runAreaUpdate: function(id, extra) {
		var request = '/areas/view/' + id + '/';
		if (!extra || extra == '') {
		    request += 'nosort/';
		}
		else {
		    request += extra + '/';
		}
		
		request += 'ajax/'
	
		var r_key = request;
		var page = null;
		var params = /^(.*)\/page:(\d+)(\/.*)?$/.exec(request);
		if (params) {
		    r_key = params[1] + params[3];
		    page = params[2];
		} else {
			page = 1;
		}
		if (this.cache[r_key]) {
		    this.applyAreaUpdate(this.cache[r_key], page);
		}
		else {
		    this.setSidebarLoading();
		    new Ajax.Request(request, {
				method: 'get', 
		        requestHeaders: { 'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT'  },
				onSuccess: function(r) {
				    _ft.cache[r_key] = r.responseText;
				    (function() {
				    	_ft.applyAreaUpdate(r.responseText, page);
				    }).defer();
				},
				onFailure: _ft.onAjaxFailure,
				onException: _ft.onAjaxException
		    });
		}
		_ft.loading = false;
		
		_ft_setNavState();
		
    },
    
    applyAreaUpdate: function(content, page) {
		var sidebar = $('sidebar');
		sidebar.update(content);
		sidebar.select('#sortmenu a').each(function(el) {
		    el.observe('click', function() { 
				_ft.addHashToLink(el);
				_ft.setState(el.href);
		    });
		});
		sidebar.select('.venues').each(function(venuesEl) {
		    venuesEl.select('li.venue').each(function(venueEl,index) {
				venueEl.select('a').each(function(el,index) {
				    el.observe('click', function() { 
						_ft.addHashToLink(el);
						_ft.setState(el.href);
	
						// IE won't pass this click to the surrounding <li>, as others do, so show popup explicitly.
						// For other browsers, this will happen when the click is passed up to the <li>, handled next.
						if (Prototype.Browser.IE) {
						    var id = (/^venue_(\d+)$/.exec(venueEl.id))[1];
						    var marker = _ft.markers_by_id[id];
						    if (marker) {
						    	_ft.showPopupForMarker(marker);
						    }
							
						}
				    });
				});
				venueEl.observe('click', function() { 
				    var id = (/^venue_(\d+)$/.exec(venueEl.id))[1];
				    var marker = _ft.markers_by_id[id];
				    if (marker) {
				    	_ft.showPopupForMarker(marker);
				    }
				});
				venueEl.observe('mouseover', function() {	
				    var id = (/^venue_(\d+)$/.exec(venueEl.id))[1];
				    var marker = _ft.markers_by_id[id];
				    if (marker) {
					    popUpId = window.setTimeout(function() {
							_ft.showPopupForMarker(marker);
			 			}, 500);
						_ft.toggleMarker(venueEl, true);	 			
				    }
				});
				venueEl.observe('mouseout', function() {
					if(typeof(popUpId) != undefined) {
						window.clearTimeout(popUpId);
						_ft.toggleMarker(venueEl, false);					
					}
				});
		    });

		    
		});
	    $$('#pagenav a').each(function(el) {
			el.observe('click', function(event) {
				_ft.toggleVenuesPage(el);				
				event.stop();
			});
	    });
		sidebar.select('a.hoodlink').each(function(el) {
		    el.observe('click', function() { 
				_ft.addHashToLink(el);
				_ft.setState(el.href); 
		    });
		});	
		
		if(page) {
			this.toggleVenuesPage(null, page);
		}


    },

    runVenueUpdate: function(id, extra) {
		var request = '/venues/view/' + id + '/';
		var id_num = id.split('_')[0]; //get the numeric id from the id string
		if (extra && extra != '') {
			request += extra + '/';
		}
		
		request += 'ajax/';
	
		if (this.cache[request]){
			this.applyVenueUpdate(this.cache[request]);
		} else {
		    this.setSidebarLoading();

		    new Ajax.Request(request, { 

				method: 'get', 
		        requestHeaders: { 'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT'  },
				onSuccess: function(r) {
				    _ft.cache[request] = r.responseText;
				    (function() { 
						_ft.applyVenueUpdate(r.responseText); 
						
						if($('listings')) {
							// If we had a venue state link at initial load, the map may not be initialized. 
							// So kick off a markers update from the area ID in the venue 'listings' link.
							var areaID = /\/areas\/view\/(\d+)/.exec($('listings').href)[1];						
							(function() {
							    _ft.runMarkersUpdate(areaID, function() {
									if (_ft.markers_by_id[id_num]) { //id_num must be the numeric id of the venue
										_ft.showPopupForMarker(_ft.markers_by_id[id_num]);
									}
							    });
							}).defer();
						}
				    }).defer();					
   
				},
				onFailure: _ft.onAjaxFailure,
				onException: _ft.onAjaxException
		    });
		}
		_ft.loading = false;
    },

    applyVenueUpdate: function(contents) {
		var sidebar = $('sidebar');
		sidebar.update(contents);
		sidebar.select('.actions a').each(function(el) {
		    el.observe('click', function() { 
				_ft.addHashToLink(el);
				_ft.setState(el.href); 
		    });
		    
		    if (el.id == 'previous' || el.id == 'next') {
				var vid = /venues\/view\/(\d+)/.exec(el.href)[1];
				var marker = _ft.markers_by_id[vid];
				if (marker) {
				    el.observe('click', function() {
				    	_ft.showPopupForMarker(marker);
				    });
				}
		    }
		});
	
		sidebar.select('a.hoodlink').each(function(el) {
		    el.observe('click', function() { 
				_ft.addHashToLink(el);
				_ft.setState(el.href); 
		    });
		});

		_ft_setNavState();
		
		//Add This button.
		if(typeof(addthis) != 'undefined') {
			addthis.button('.addthis_button_compact');
		}

    },

    runMarkersUpdate: function(id, onSuccessCallback) {
		if (this.markers_area_id == id) {
			return;
		} else {
			this.markers_area_id = id;
		
			var markerURL = '/areas/markerdata/' + id;

			new Ajax.Request(markerURL, {
			    method: 'get',
			    requestHeaders: { 'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT'  },
			    onSuccess: function(r) {
	
					_ft.makeMarkers(r.responseText);
					if (onSuccessCallback) {
						onSuccessCallback.defer();
					}
			    },
			    onFailure: _ft.onAjaxFailure,
			    onException: _ft.onAjaxException
			});		
		}
    },

    setToMap2: function() {
		$('map').className = 'map-hidden';
    },

    setSidebarLoading: function() {
		var el = $('sidebar_contents');
		var loading = '<div class="loading">Loading...</div>';
		if (el) {
			el.update(loading);
		} else {
			$('sidebar').update(loading);
		}
		$('mapoverlay').hide();
    },

    toggleMarker: function(el, on) {
		var id = (/^venue_(\d+)$/.exec(el.id))[1];
		//el.className = 'venue ' + (on ? 'venue_highlight' : '');
		var marker = this.markers_by_id[id];
		if (marker) { marker.toggleHighlight(on); }
    },

    toggleVenuesPage: function(pageLink, page) {

		var pageID = 'venues_' + (page ? page : pageLink.innerHTML);
		var pages = $$('#sidebar .venues');

		for (var i = 0, ic = pages.length; i < ic; ++i) {
		    if (pages[i].id == pageID) {
		    	pages[i].show();
		    } else {
		    	pages[i].hide();
		    }
		}
    },

    // Init the neighborhoods map in div#gmap.
    initMap: function() {
    
		this.map = new google.maps.Map2($('gmap'));
		this.map.disableDoubleClickZoom();

		this.tilelayer = new google.maps.TileLayer(new google.maps.CopyrightCollection(''),13,17); 
		this.tilelayer.getTileUrl = function (a, b) { return "/img/map/" + _ft.tileToQuadKey(a.x, a.y, b) + ".jpg"; }
		this.tilelayer.isPng = function(){ return true }; 
	
		this.ftmap = new google.maps.MapType([this.tilelayer], G_HYBRID_MAP.getProjection(), "Food Tyrant"); 
	//	this.ftmap = new google.maps.MapType([this.tilelayer], G_SATELLITE_MAP.getProjection(), "Food Tyrant",{errorMessage:"nothing here"}); 
		this.ftmap.getTextColor = function() {return "#0000FF";}; 
	
		this.map.addMapType(this.ftmap); 
		
		this.icon = new google.maps.Icon();
		this.icon.image = this.marker_off_image;
		this.icon.iconSize = new google.maps.Size(20, 20);
		this.icon.iconAnchor = new google.maps.Point(10, 10);
		this.icon.infoWindowAnchor = new google.maps.Point(10, 10);
		this.icon.transparent = this.marker_off_image;
		this.icon.imageMap =[7,1,11,1,20,7,20,11,11,20,7,20,1,11,1,7];
	
	//	this.moveMap(40.76284,-73.971157, false);
	
		this.map.setMapType(this.map.getMapTypes()[3]);
	
		this.initPopup();
    },

    initPopup: function() {
		if (this.popup) { return; }
	
		FTPopupInit();
		this.popup = null;
		this.popup = new FTPopup();
		this.map.addOverlay(this.popup);
		
		google.maps.Event.addListener(this.map, 'dragstart', function() {
		    //_ft.hidePopup();
		});
	
		this.preloadImage('/img/info_bg.png');
		this.preloadImage('/img/info_stem.png');
		this.preloadImage(this.marker_off_image);
		this.preloadImage(this.marker_on_image);
    },

    showPopupForMarker: function(marker) {
		this.initPopup();
		this.popup.setMarker(marker);
	
		if (this.lastHighlightMarker && this.markers_by_id[this.lastHighlightMarker]) {
		    this.markers_by_id[this.lastHighlightMarker].toggleHighlight(false, true);
		}
		marker.toggleHighlight(true, true);
		this.lastHighlightMarker = marker.id;
		this.moveMap(marker.point.lat(), marker.point.lng());
		$$('.closeinfowindow').each(function(w){
			w.observe('click',function(){
				_ft.hidePopup();
			});
		});

    },

    hidePopup: function() {
		if (!this.popup) {
			return;
		}
	
		this.popup.hide();
	
		if (this.lastHighlightMarker && this.markers_by_id[this.lastHighlightMarker]) {
		    this.markers_by_id[this.lastHighlightMarker].toggleHighlight(false, true);
		}
		
		this.lastHighlightMarker = null;
    },

    tileToQuadKey: function(x, y, zoom) { 
		var quad = ""; 
		for (var i = zoom; i > 0; i--){
		    var mask = 1 << (i - 1); 
		    var cell = 0; 
		    if ((x & mask) != 0) {
			  	cell++;
		    }
		    if ((y & mask) != 0) {
			  	cell += 2;
		    }
		    quad += cell; 
		} 
		return quad; 
    },

    moveMap: function(lat, lng) {
		if (!this.mapCenteredOnce) {
		    this.map.setCenter(new google.maps.LatLng(lat, lng), 15, this.map.getMapTypes()[3]);//this.map.getCurrentMapType());
		    this.setToMap2();
		    this.mapCenteredOnce = true;
		} else {
		    this.map.panTo(new google.maps.LatLng(lat, lng));
		}
		
    },

    makeMarkers: function(xml) {
    
    	if(typeof google.maps.Xml != 'undefined') {

			var xmlDoc = google.maps.Xml.parse(xml);			
			
			var locations = xmlDoc.documentElement.getElementsByTagName('location');

			for (var i = 0; i < this.markers.length; ++i) {
			    this.map.removeOverlay(this.markers[i].gmarker);
			}

			if(locations.length > 0) {
			
				this.moveMap(parseFloat(xmlDoc.documentElement.getAttribute('lat')),parseFloat(xmlDoc.documentElement.getAttribute('lng')));
			
				
				this.markers = [];
				this.markers_by_id = {};
		
				for (var i = 0; i < locations.length; ++i) {
				    var location = locations[i]
				    var marker = {
						id: location.getAttribute('id'),
						point: new google.maps.LatLng(parseFloat(location.getAttribute('lat')), parseFloat(location.getAttribute('lng'))),
						html: location.firstChild.nodeValue,
						label: location.getAttribute('label'),
						hot: false,
						toggleHighlight: function(on, persistent) {
						    if (!persistent && this.hot) { return; }
						    this.hot = persistent && on;
						    this.gmarker.setImage(on ? _ft.marker_on_image : _ft.marker_off_image);
						}
				    };
				    this.markers.push(marker);
	
				    this.markers_by_id[marker.id] = marker;
			
				    marker.gmarker = new google.maps.Marker(marker.point, this.icon);
				    marker.gmarker._ft_marker_id = marker.id;
		
				    this.map.addOverlay(marker.gmarker, 15);
			
				    google.maps.Event.addListener(marker.gmarker, 'click', (function() {
				    	if (this.hot == true) {
							_ft.hidePopup();
				    	} else {
					    	_ft.showPopupForMarker(this);
					    	return this.gmarker;
				    	}
				    }).bind(marker));
				    google.maps.Event.addListener(marker.gmarker, "mouseover", (function() {
						this.toggleHighlight(true);
						var venueEl = $('venue_' + this.id);
						if (venueEl) {
						    venueEl.className = 'venue venue_highlight';
						}
						return this.gmarker;
				    }).bind(marker));
				    google.maps.Event.addListener(marker.gmarker, "mouseout", (function(){
						this.toggleHighlight(false);
						var venueEl = $('venue_' + this.id);
						if (venueEl) {
						    venueEl.className = 'venue';
						}
						return this.gmarker;
				    }).bind(marker));
				}			
			} else {
				this.hidePopup();
			}
    	}

    },
    
    preloadImage: function(src) {
		var img = new Image();
		img.src = src;
		this.preloadImages.push(img);
    },

    addHashToLink: function(link) {
		$j(link).attr({
			'href' : '#/' + link.pathname.replace(/^\//,'')
		});
    },

    onAjaxFailure: function(response) {
		this.loading = false;
    },
	
    onAjaxException: function(response, e) {
		this.loading = false;
    }
}


/// Intialization routines that run on load.

// Initialize mouseovers on the left-side image map.
// Works with default or index layouts.
// Should be called on DOM loaded.
function ft_initAreasMap() {

	// in iphone mode, we just have the sidebar, no maps, and run with static links.
	//Just kidding.
/*
    if (_ft.iphone) {
		$('mapwrapper').remove();
		$(document.body).addClassName('iphone');
    } else {
*/
		$$('#overlaymap area').each(function(el) {
		    el.observe('mouseover', function() {
				$('maphighlights').className = el.className;
		    });
		    el.observe('mouseout', function() {
				$('maphighlights').className = '';
		    });
		});
/*     } */
}

// Additional initialization (1 of 2) for the main page (index layout).
// Should be called on DOM loaded.
function ft_initMainPage1() {
    //if (_ft.iphone) { return; }
    _ft.haveHashAction = window.location.href.match(/\/#\/\w+\/\w+/);
    if (_ft.haveHashAction) {
		_ft.setSidebarLoading();
    }
}

// Additional initialization (2 of 2) for the main page (index layout).
// Should be called on page loaded.
function ft_initMainPage2() {

    //if (_ft.iphone) { return; }

    if (!google.maps) {
		google.load("maps", "2", {
		    "callback": function(){
				_ft_initMainPageAfterMaps.defer();
		    }
		});
    } 
    else {
    	_ft_initMainPageAfterMaps();
    }
	
}

function _ft_initMainPageAfterMaps() {
    if (_ft.haveHashAction) { //if there is a hash and anything after the hash in the URL
	    _ft_initNav();
		_ft.initMap();
		$j.address.change(); //we have to call this explicitly here for deep-linked page refreshes
    } else {
    	$j('#overlaymap area').live('click',function(event){
    		event.preventDefault();
			$j.address.value($j(this).attr('href'));
    	});
    	
		$j('#overlaymap area').hover(
			function(event){
				$j('#nav li a.' + $j(this).attr('class')).addClass('over');
			},
			function(event){
				$j('#nav li a.' + $j(this).attr('class')).removeClass('over');
			}
		);
		

		$j('#sidebar div.featured a').live('click',function(event) {
			event.preventDefault();
			$j.address.value($j(this).attr('href'));
			
		});
		
		_ft_initNav();
		_ft.initMap();
    }
	
	
}

function _ft_initNav() {
	$j('#nav li a.hood').live('click',function(event){
		event.preventDefault();
		$j.address.value($j(this).attr('href'));
		_ft.hidePopup();
	});
	$j('#nav li a').hover(
		function(event){
			$j('#maphighlights').addClass($j(this).attr('class'));
		},
		function(event){
			$j('#maphighlights').attr({ 'class' : '' });
		}
	);
}

function _ft_setNavState() {
	var paths = $j.address.pathNames();
	var controller = paths[0];
	var area = null;
	var i = null;
	
	if(controller == 'areas') {
		area = paths[2].split('_')[0];
	} else if(controller == 'venues') {
		if(typeof($j('.venue').attr('class')) != 'undefined') {
			area = $j('.venue').attr('class').split('area-')[1];
		}
		
	} else {
		return;
	}

	if(typeof area == 'undefined' || area == '' || area == null) {
		return;
	} else {
		$$('#nav a.hood').each(function(e){
			e.removeClassName('on');
		});
	
		$$('#nav a#hood' + area).each(function(e){
			e.addClassName('on');
		});	
	}
	
}

function _ft_initAddress() {
	$j.address.change = function(){

		if(_ft.map != null) {
			_ft.setState();
		}
	};
}

_ft.initiphone = function() {
/*
	var address = $j('.venue-address-actual').text();
	var fulladdress = $j('.venue-address').text();
	var name = $j('.venue-name').text();
	
	$j('.hood-nyc a').text('Recent'); 
	
	$j('#sidebar').before($j('#logo').clone());
	$j('#sidebar').before('<a href="" id="iphone-nav">Menu</a>');
	$j('#nav ul').prepend('<li><a href="" id="iphone-nav-back">Back</a></li>').append($j('#footer li'));
	$j('.venue-address').html('<a href="http://maps.google.com/maps?q=' + name + ', ' + address + ', New York, NY">' + fulladdress + '</a>');	
	$j('#iphone-nav').live('click',function(event){
		event.preventDefault();
		$j('#content').hide();
		$j('#header').show();
	});
	$j('#iphone-nav-back').live('click',function(event){
		event.preventDefault();
		$j('#header').hide();
		$j('#content').show();
	});
*/
}


