/////////////
// util.js //
/////////////

function startLoadingAnimation() {
	document.getElementById('loading_animation').style.visibility = 'visible';
}

function stopLoadingAnimation() {
	document.getElementById('loading_animation').style.visibility = 'hidden';
}

function removePreloadedImages(evt) {
	$(this).stopObserving();
}

function preloadImage(url) {
	var img = new Image();
	img.src = url;
	Event.observe(img, "load", removePreloadedImages.bindAsEventListener(img));
}


function asyncGetJson(url, cb, eb) {
	var opt = {
			 method: 'get',			 
			 onSuccess: cb,
			 on404: function(){alert('404 error, unable to load.')},
			 onFailure: eb
			};
	return (new Ajax.Request(url+'&nocache='+(new Date()).getTime(), opt));	
}

function findImagesArray(marker) {
	for (var i in marker)
	{
		if (eval("typeof marker." + i) == "object")
		{
			try {
				if (eval("typeof marker." + i + "[0].src") != "undefined")
				{
					return i;
				}
			}
			catch (e) {}
		}
	}
	return '';
}

/////////////////////////////
// gxmarker.yelp.js /////////
// based on gxmarker.1.js //
////////////////////////////
// This has been slightly modified to add a target variable for the clickURL


function GxMarkerNamespace() {

var n4=(document.layers);
var n6=(document.getElementById&&!document.all);
var likesDXFilters = false;
var ie=(document.all && !window.opera);
if (ie) {
	var ua = navigator.userAgent;
	var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
	if (re.exec(ua) != null) {
		var rv = parseFloat( RegExp.$1 );
		if (rv >= 7) { 
			likesDXFilters = true;
		} else if ((rv >= 6) && ((new RegExp("SV1")).exec(ua) != null)) { 
			likesDXFilters = true;
		}
	}

}
window.likesDXFilters = likesDXFilters;
window.ie = ie;

var o6=(navigator.appName.indexOf("Opera") != -1);
var safari=(navigator.userAgent.indexOf("Safari") != -1);

function GxMarker(point, icon, tooltipHtml, clickURL, target) {
	this.inheritFrom = GMarker;
	this.inheritFrom(point, icon);
	if ( typeof tooltipHtml != "undefined" ) {
		this.setTooltip( tooltipHtml );
	}
	if(!target){this.target='_blank';}else{this.target=target}
	this.clickURL = clickURL;
	this.imagesArray = '';
	this.oldImagePath = "";
	this.hoverIcon = createSliceIcon(icon.num, SLICE_STYLE_HIGHLIGHTED);
	this.events = new Array();
}

GxMarker.prototype = new GMarker(new GLatLng(1,1));

GxMarker.prototype.setTooltip = function( string ) {
    this.tooltip = new Object();
    //this.tooltip.opacity  = 70;
    this.tooltip.contents = string;
};

GxMarker.prototype.showHighlight = function() {
	if (this.imagesArray.length == 0) {
    	this.imagesArray = findImagesArray(this);
	}

	if (this.imagesArray.length != '') {
		if (this.oldImagePath.length == 0) {
			this.oldImagePath = this[this.imagesArray][0].src;
		}
		if (ie && likesDXFilters) {
			this[this.imagesArray][0].style.filter = 
				'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.hoverIcon.image + '")';

		} else {
			this[this.imagesArray][0].src = this.hoverIcon.image;
		}
		this[this.imagesArray][0].style.zIndex = 4999;
		this.redraw(true);
	}
}

GxMarker.prototype.removeHighlight = function() {
	if (this.imagesArray.length == 0) {
    	this.imagesArray = findImagesArray(this);
	}

	if (this.imagesArray.length > 0) {
		if (ie && likesDXFilters) {
			this[this.imagesArray][0].style.filter = 
				'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.oldImagePath + '")';
		} else {
			this[this.imagesArray][0].src = this.oldImagePath;
		}
		this.oldImagePath = "";
		this[this.imagesArray][0].style.zIndex = 4998;
		this.redraw(true);
	}
}

GxMarker.prototype.initialize = function( a ) {
    try {
        GMarker.prototype.initialize.call(this, a);
        // Setup the mouse over/out events
		this.events.unshift(GEvent.bind(this, "mouseover", this, this.onMouseOver));
		this.events.unshift(GEvent.bind(this, "mouseout",  this, this.onMouseOut));
		this.events.unshift(GEvent.bind(this, "click",  this, this.onClick));
		this.map = a;
    } catch(e) {
    	console.error(e);
    }
}

GxMarker.prototype.remove = function( a ) {
    GMarker.prototype.remove.call(this);
    if ( this.tooltipObject )
        //this.map.div.removeChild(this.tooltipObject);
        document.body.removeChild(this.tooltipObject);
	this.removeEvents();
   this.map = null;
}

GxMarker.prototype.onInfoWindowOpen = function() {
    this.hideMouseOver();
    GMarker.prototype.onInfoWindowOpen.call(this);
}

GxMarker.prototype.onClick = function() {
	if (this.clickURL)
	{
		window.open(this.clickURL, this.target);
	}
}

GxMarker.prototype.onMouseOver = function() {
    this.showMouseOver();
};

GxMarker.prototype.onMouseOut = function() {
    this.hideMouseOver();
};

GxMarker.prototype.showMouseOver = function() {
	var bb  = this.map.getBounds();
    if ( this.tooltip ) {
        if ( typeof this.tooltipObject == "undefined" ) {
            this.tooltipObject = document.createElement("div");
            this.tooltipObject.style.display    = "none";
            this.tooltipObject.style.position   = "absolute";
            //this.tooltipObject.style.background = "#fff";
            this.tooltipObject.style.padding    = "0";
            this.tooltipObject.style.margin     = "0";
            this.tooltipObject.style.zIndex     = 50000;
            this.tooltipObject.innerHTML        = "<div class=\"markerTooltip\">" + this.tooltip.contents + "</div>";

/*
            var opacity = this.tooltip.opacity / 100;
            this.tooltipObject.style.MozOpacity = opacity;
            this.tooltipObject.style.filter     = "alpha(opacity=" + this.tooltip.opacity + ")";
            this.tooltipObject.style.opacity    = opacity;
*/

            document.body.appendChild(this.tooltipObject);
        }

	// make sure the point is currently within map bounds
	if(bb.contains(this.getPoint())){
		var tlcLatLng = this.map.fromContainerPixelToLatLng(new GPoint(0,0), true);
		var tlcDivPixel = this.map.fromLatLngToDivPixel(tlcLatLng);
		var pointDivPixel = this.map.fromLatLngToDivPixel(this.getPoint());
		var c = new GPoint(pointDivPixel.x-tlcDivPixel.x, pointDivPixel.y-tlcDivPixel.y);
		var mapPos = findPosition(this.map.getContainer());

		this.tooltipObject.style.left = "-1000px";
        this.tooltipObject.style.top = "-1000px";
        this.tooltipObject.style.display = "block";
		
		// is it the location pin?
		var pin = (this.tooltip.contents.indexOf('loc_pin_flag')>=0) ? true : false;
		
        var tipLeft = c.x - this.getIcon().iconAnchor.x + mapPos[0];
        if(pin){
			tipLeft -= ((this.getIcon().iconSize.width/2)-6);
		}else if (tipLeft > (document.body.offsetWidth/2)) {
        	tipLeft -= this.tooltipObject.offsetWidth;
        } else {
        	tipLeft += this.getIcon().iconSize.width;
        }
        this.tooltipObject.style.left = tipLeft + "px";

        var tipTop = c.y - this.getIcon().iconAnchor.y + mapPos[1];
        if(pin){
			tipTop -= ((this.getIcon().iconSize.height*2)+1);
		}else if ((c.y + this.map.getContainer().offsetTop) > (this.map.getContainer().offsetHeight/2)) {
        	tipTop -= this.tooltipObject.offsetHeight;
        } else {
        	tipTop += this.getIcon().iconSize.height;
        }
        this.tooltipObject.style.top = tipTop + "px";
		// reset locPin timeout
		if(pin&&this.locPinTimeout){window.clearTimeout(this.locPinTimeout);}
    }
	this.showHighlight();
	}
	
}

GxMarker.prototype.hideMouseOver = function() {
    if ( typeof this.tooltipObject != "undefined" ) {		
		if(this.tooltip.contents.indexOf('loc_pin_flag')>=0){
			// delay locPin tooltip hide.
			Yelp.tooltipHolder = this.tooltipObject;
			this.locPinTimeout = window.setTimeout('Yelp.tooltipHolder.style.display = "none";Yelp.tooltipHolder=null;',2000);
		}else{
			this.tooltipObject.style.display = "none";
		}
    }
	this.removeHighlight();
}

GxMarker.prototype.removeEvents = function () { 
	while (this.events.length > 0) { 
		GEvent.removeListener(this.events.shift());
	}
}
GxMarker.prototype.unload = function () {
	this.removeEvents(); 	 
	this.tooltipObject = null;
	this.tooltip = null;
	this.imagesArray = '';
	this.map = null;
	this.hoverIcon = null;
}
function makeInterface(a) {
    var b = a || window;
    b.GxMarker = GxMarker;
}

makeInterface();
}

GxMarkerNamespace();

// Yelp extension
GMap2.prototype.findCenterAndZoom = function(points) {
	var defaultZoom = 14;
	var center = null;
	if (points.length == 1){
		center = new GLatLng(points[0]['latitude'], points[0]['longitude']);
		return {zoom: defaultZoom, center: center};
	}

	var bounds = new GLatLngBounds(new GLatLng(90.0,180.0), new GLatLng(-90.0,-180.0));
	for (var i = 0; i < points.length; i++){
		if(points[i]['latitude'] && points[i]['longitude']){
			bounds.extend(new GLatLng(parseFloat(points[i]['latitude']), parseFloat(points[i]['longitude'])))
		}
	}

	center = bounds.getCenter();
	
	var newZoom = this.getBoundsZoomLevel(bounds);
	if (newZoom <= 0 || newZoom >= defaultZoom) {
		newZoom = defaultZoom;
	}

	return {zoom: newZoom, center: center, bounds: bounds};
}


//////////////////////////
// Original maputil.js //
/////////////////////////

var SLICE_STYLE_NORMAL = 1;
var SLICE_STYLE_HIGHLIGHTED = 2;
var SLICE_STYLE_FADED = 3;

function createSliceIcon(num, style) {
	var icon = new GIcon();
	// is it the location pin?
	var pin = typeof(num)=='number' ? false : true;
	if (!pin&&(num < 0)) {
		icon.image = imagesPrefix+'map/'+ ((style == SLICE_STYLE_HIGHLIGHTED) ? 'marker_star_highlighted.png' : 'marker_star.png');
	} else {
		var style_dir;
		if (style == SLICE_STYLE_NORMAL) {
			style_dir = 'marker';
		} else if (style == SLICE_STYLE_HIGHLIGHTED) {
			style_dir = 'marker_highlighted';
		} else if (style == SLICE_STYLE_FADED) {
			style_dir = 'marker_faded';
		}
		icon.image = imagesPrefix+'map/' + style_dir + '/' + num + '.png';
	}
	if(!pin){
		icon.iconSize = new GSize(20, 29);		
		icon.shadowSize = new GSize(38, 29);
		icon.shadow = imagesPrefix+'map/marker_shadow.png';
		icon.iconAnchor = new GPoint(15, 29);
		icon.infoWindowAnchor = new GPoint(15, 3);
	}else{
		icon.iconSize=new GSize(33,23);
		icon.iconAnchor=new GPoint(11, 21);
		icon.infoWindowAnchor=new GPoint(8, 1);
	}	
	icon.num = num;
	return icon;
};

function createBizMarker(biz, number, faded) {
	var point = new GPoint(biz['longitude'], biz['latitude']);

	var icon = createSliceIcon(number, faded ? SLICE_STYLE_FADED : SLICE_STYLE_NORMAL);

	// render popup HTML
	var popupHTML = '<div class="maptip"><table cellspacing="0" cellpadding="0" border="0"><tr valign="top">';
	if (biz['photos'].length > 0) {
		bizPhotoUrl = imagesHostUrl + 'bphoto/' + biz['photos'][0]['id'] + '/ms';
		preloadImage(bizPhotoUrl);
		popupHTML += '<td><img src="' + bizPhotoUrl + '"></td><td width="10">&nbsp;</td>';
	}
	popupHTML += '<td>';
	if (biz['review_count'] > 0) {
		popupHTML += '<span style="vertical-align: -5px;">' + Yelp.HTML.stars(biz['rating'], false) + '</span> <em style="color: #555; font-weight: 500; font-size: 11px;"><span>based on</span> ' + biz['review_count'] + ' review' + (biz['review_count'] != 1 ? 's' : '') + '</em><br/>';
	}
	popupHTML += '<h3>' + biz['name'] + '</h3>';

	if (biz['phone']) {
		popupHTML += '<b>' + biz['phone'] + '</b>';
	}
	if (biz['neighborhoods'].length > 0) {
		popupHTML += '<br/>Neighborhood: ' + biz['neighborhoods'].join(', ');
	}
	if (biz['address1']) {
		popupHTML += '<br/>' + biz['address1'];
	}
	if (biz['address2']) {
		popupHTML += '<br/>' + biz['address2'];
	}
	popupHTML += '<br/>';
	if (biz['city']) {
		popupHTML += biz['city'] + ', ';
	}
	if (biz['state']) {
		popupHTML += biz['state'] + ' ';
	}
	if (biz['zip']) {
		popupHTML += biz['zip'];
	}
	popupHTML += '</td>';
	popupHTML += '</tr></table></div>';

	clickURL = '/biz/' + biz['id'];

	return new GxMarker(point, icon, popupHTML, clickURL);
};

function getAdjustedMapBounds(map, mapContainer) {
	var adjBounds = {};
	var topDead = 25;
	var leftDead = 10;
	var rightDead = 5;
 	var bounds = map.getBounds();
	var lonPerPix = (bounds.getNorthEast().lng() - bounds.getSouthWest().lng())/mapContainer.clientWidth;
	var latPerPix = (bounds.getNorthEast().lat() - bounds.getSouthWest().lat())/mapContainer.clientHeight;
	
	adjBounds['minlon'] = bounds.getSouthWest().lng() + leftDead*lonPerPix;
	adjBounds['maxlon'] = bounds.getNorthEast().lng() - rightDead*lonPerPix;
	adjBounds['minlat'] = bounds.getSouthWest().lat();
	adjBounds['maxlat'] = bounds.getNorthEast().lat() - topDead*latPerPix;
	return adjBounds;
};


// functions for nearby biz map

//////////////////////
// mappity map map //
/////////////////////

var map = null;
var markers = null;
var highlightMarker = null;
var firstQuery = true;
var NEARBY_BIZ_COUNT = 5;

// this method highlights the appropriate marker on 
// the map when you enter or leave a particular element
// (usually a div) with class 'highlight_marker_box'.
// We require this particular class because the 
// event may be fired by any element within the box,
// so we need some way of indentifying the containing box
//
// You should set up this function to handle both 
// 'mouseover' and 'mouseout' events; it'll look at where
// the mouse pointer is to figure out what to do
function updateHighlightMarker(evt) {
	// get our target element
	var target = $(findEventTarget(evt));
	// this event came from something within the box
	if (!target.hasClassName('highlight_marker_box')) {
		target = target.up('.highlight_marker_box');
	}
	// get the index of the marker that target corresponds to 
	var target_id_parsed = target.id.split('_');
	var index = target_id_parsed[target_id_parsed.length-1];

	// are we in the box or out of it?
	if (Position.within(target, Event.pointerX(evt), Event.pointerY(evt))) {
		if (!highlightMarker) { // no current highlight
			// set the global highlight marker
			highlightMarker = new GMarker(markers[index].getPoint(), 
										  {icon:createSliceIcon(parseInt(index)+Yelp.pageStart, SLICE_STYLE_HIGHLIGHTED), zIndexProcess:function(marker, b) { return 10000000; } }
										 );
			// add the highlight marker to the map
			map.addOverlay(highlightMarker);
		}
	}
	else {
		if (highlightMarker) { // current highlight
			// remove the (global) highlight marker
			map.removeOverlay(highlightMarker);
			highlightMarker = null;	
		}
	}
}

function showPopupIndex(evt) {
	var target = $(findEventTarget(evt));
	var target_id_parsed = target.id.split('_');
	var index = target_id_parsed[target_id_parsed.length-1];
	markers[index].showMouseOver();
	highlightMarker = new GMarker(markers[index].getPoint(), createSliceIcon(parseInt(index), SLICE_STYLE_HIGHLIGHTED));
	map.addOverlay(highlightMarker);
}

function hidePopupIndex(evt) {
	var target = findEventTarget(evt);
	var target_id_parsed = target.id.split('_');
	var index = target_id_parsed[target_id_parsed.length-1];
	markers[index].hideMouseOver();
	map.removeOverlay(highlightMarker);
	highlightMarker = null;	
}

function handleQueryResponse(results) {
results = JSON.parse(results.responseText);
	map.clearOverlays();

	if (!results['success']) {
		set_element_html('nearby_biz_list', '<span class="error">' + results['result'] + '<'+'/span>');
		stopLoadingAnimation();
		return;
	}

	var biz;
	var near_cat_select=$('nearby_cat_select');
	markers = new Array();
	var r = '';
	var bizInfos = results['result']['biz_list'];

	if ((bizInfos.length == 0)||(bizInfos.length==1 && bizInfos[0].id==json_biz.id)) {
		r += 'No matching '+somewhatSanitize(near_cat_select[near_cat_select.selectedIndex].innerHTML)+' found.  Try <a href="#" onclick="map.setZoom(map.getZoom()-1);return false">zooming out<'+'/a> on the map.';
	} else {
		var index = 0;
		r += '<ul id="mapsearch_results">';
		for (var i = 0; (i < bizInfos.length) && (index < NEARBY_BIZ_COUNT); i++) {
			biz = bizInfos[i];

			if (biz['id'] == json_biz.id) {
				continue;
			}

			index++;

			var bizdUrl = '/biz/' + biz['id'];
			// list item
			r += '<li>'+ index + '.&nbsp;';
			if(biz['longitude']&&biz['latitude']){
				r += '<a id="nearby_biz_name_'+ index + '" href="' + bizdUrl + '">' + biz['name'] + '<'+'/a>';
			}else{
				r += '<a href="' + bizdUrl + '">' + biz['name'] + '<'+'/a>';
			}
			// Should we check for a 0 rating as well?
			if ((biz['rating'] != null) && (biz['review_count'] > 0)) {
				r += '<br/><span class="nonwrapping">' + Yelp.HTML.stars(biz['rating'], true);
				r += '<'+'/span> <em class="smaller">' + biz['review_count'] + ' review' + (biz['review_count'] != 1 ? 's' : '') + '<'+'/em>';
			}			
			r += '<'+'/li>';

			var m = createBizMarker(biz, index, true);
			markers[index] = m;
			map.addOverlay(m);
		}
		if(bizInfos.length>=5){
			var spRE = /%20/g;
			var mnb = '<li id="more_nearby_results"><a href="/search?find_loc='+encodeURIComponent(json_biz.address1+','+json_biz.city+','+json_biz.state);
			mnb.replace(spRE,'+');
			if(near_cat_select[near_cat_select.selectedIndex].value!='root'){
				mnb+='&cflt='+encodeURIComponent(near_cat_select[near_cat_select.selectedIndex].value);
			}
			mnb+='&z=15">... More Nearby '+somewhatSanitize(near_cat_select[near_cat_select.selectedIndex].innerHTML)+' &raquo;</a></li>';
			r+= mnb;
		}
		r += '<'+'/ul>';
	}
	
	set_element_html('nearby_biz_list', r);
	
	for(var i=1;i<=NEARBY_BIZ_COUNT;i++){
		var el_index = $('nearby_biz_name_'+i);
		if(el_index){
			Element.observe(el_index,'mouseover',showPopupIndex);
			Element.observe(el_index,'mouseout',hidePopupIndex);
		}
	}

	biz = json_biz;
	map.addOverlay(createBizMarker(biz, -1, false));

	stopLoadingAnimation();
	near_cat_select=null;
}

function handleQueryError(req) {
	set_element_html('nearby_biz_list', '<span class="error">Error connecting to server.  Please try again later.<'+'/span>');
	stopLoadingAnimation();
}



function updateResults() {
	startLoadingAnimation();

	var params = getAdjustedMapBounds(map, document.getElementById("mapdiv"));
	params['type'] = 'browse';
	var select_element = document.getElementById('nearby_cat_select');
	params['arg'] = select_element.options[select_element.selectedIndex].value;
	params['sort'] = 'rating';
	params['start'] = 0;
	params['count'] = NEARBY_BIZ_COUNT + 1;
	if (firstQuery) {
		params['ch'] = '1';
	}

	firstQuery = false;

	var url = '/mapsearch_query/search?' + Yelp.encodeQueryComponents(params);
	asyncGetJson(url, handleQueryResponse, handleQueryError);
}

var copyrightTimer = null;

function initMap() {
	map = new GMap2(document.getElementById("mapdiv"));

	map.addControl(new GSmallZoomControl());
	map.setCenter(new GLatLng(parseFloat(json_biz.latitude), parseFloat(json_biz.longitude)), 15);

	GEvent.addListener(map, "moveend", updateResults);

	updateResults();
	
	copyrightTimer = window.setInterval('makeCopyrightSmaller()', 150);	
}
// for unloading nearby_biz map objects
function uninitMap(){
	// 'this' should be the ID prefix for the elements you want to stop observing.
	for(var i=1;i<=NEARBY_BIZ_COUNT;i++){
		var el_index = $(this+'_'+i);
		if(el_index){
			Element.stopObserving(el_index,'mouseover',showPopupIndex);
			Element.stopObserving(el_index,'mouseout',hidePopupIndex);
		}
	}
	if(map){
		map.clearOverlays.call(map);
		GUnload();
	}
	markers = null;
	map = null;
}
function makeCopyrightSmaller() {
	if (map.isLoaded()){
		for(var i = 0; i < map.getContainer().childNodes.length; ++i) {
			if(map.getContainer().childNodes[i].innerHTML.indexOf(String.fromCharCode(169)) !== -1){
      			map.getContainer().childNodes[i].style.fontSize = '9px';
      			window.clearInterval(copyrightTimer);
      			break;
    		}
    	}
  	}
}

Yelp.mapScrollObserver = function (event) {
	if(!Yelp.prevent_scroll){
		// check if user has scrolled to the point where we would need to move the map
		if (Yelp.mTest) { 
			clearInterval(Yelp.mTest);
		} else { 	
			Yelp.startScroll = document.documentElement.scrollTop;
		}
		Yelp.mTest = setInterval("Yelp.moveTest()", 300);
	}
}

// checks how far user has scrolled window, and moves map accordingly.
Yelp.moveTest = function (){
	var num = findScrollDist();	
	if(Yelp.startScroll==num){
		clearInterval(Yelp.mTest);
		Yelp.mTest = null;
		Yelp.moveBox(num);	// right now moveBox must be defined seperately for each map page.
	}	
	Yelp.startScroll = num;
}

