////////////////////////////////
// Category picker functions //
//////////////////////////////

var biz_details_category_map = new Object();
biz_details_category_map['loaded'] = false;
var ogCats = null;
var biz_detailsnewCat = '';

Yelp.categoryPicker = function(aLink){
	if(!window.biz_detailsdraw_category){
		Yelp.addScript(jsPrefix+'category_picker.js','catPickJs',[window,'biz_detailsdraw_category'],function(){Yelp.fillBizCats(aLink);});
	}else{
		Yelp.fillBizCats(aLink);
	}
}
Yelp.fillBizCats = function(aLink){
	var xmlHttpReq = Ajax.getTransport();
	if(xmlHttpReq){
		var coords = findPosition(aLink.parentNode);
		Yelp.posX = coords[0];
		Yelp.posY = coords[1];
		var catBox = $('catBox');
		if(!catBox){
			catBox = document.createElement('div');
			catBox.id = 'catBox';
			document.body.appendChild(catBox);
			var params = {'biz_id':json_biz.id, evalScripts:true}
			var catBoxFill = new Yelp.async_fill('catBox',"/pop_fill/catBox", params);
			catBoxFill.fetch_contents();
			catBoxFill=null;
		}
		
		catBox.style.cssText='top:'+coords[1]+'px;left:'+coords[0]+'px;';
		if(!Element.hasClassName(catBox,'loaded')){Element.addClassName(catBox,'loaded');}
		
	}else{
		window.location = aLink.href;
	}
}

function charCountDown(texta, limit){
	countChars(texta, limit);
	var count = limit - texta.value.length;
	$('messageCharCount').innerHTML = '('+count+' characters left)';
}

var send2phonePop = null;
function initSend2Phone(aLink,reply){
	if(!send2phonePop){
		send2phonePop = new Yelp.popBox;
		Event.observe(window,'unload',function(){send2phonePop=null;});
	}
	if(!send2phonePop.opened){
		// shorten address 1
		var truncAddress = json_biz.address1;
		var truncDict = {'street': 'St', 'avenue': 'Ave', 'alley': 'Aly', 'road': 'Rd', 'boulevard': 'Blvd', 'place': 'Pl', 'drive': 'Dr', 'center': 'Ctr', 'circle': 'Cir', 'court': 'Ct', 'highway' :'Hwy', 'expressway': 'Expy', 'parkway': 'Pkwy','junction':'Jct' ,'freeway':'Fwy', 'lane': 'Ln'};
		for (var i in truncDict){
			if((truncAddress.substr((truncAddress.length-i.length),truncAddress.length)).toLowerCase()==i){
				truncAddress = truncAddress.substr(0,(truncAddress.length-i.length))+truncDict[i];
				break;
			}
		}
		var phoneStripped = '';
		if(json_biz.phone){
			// reformat phone number, so it can be recognized by mobile phones
			var tagRE = /\(|\)/gi;
			phoneStripped = json_biz.phone.replace(tagRE,'');
			phoneStripped = phoneStripped.replace(' ','-');			
		}
		var cross_streets = '';
		if (json_biz.cross_streets && json_biz.cross_streets_miniprefix) {
			cross_streets = '\n' + json_biz.cross_streets_miniprefix + ' ' + json_biz.cross_streets;
		}
		var bizTrucName = json_biz.name;
		var bizMUrl = 'http://m.yelp.com/biz/'+json_biz.id;
		var bizInfo = bizTrucName+'\n'+truncAddress+cross_streets+'\n'+json_biz.city+'\n'+phoneStripped+'\n'+bizMUrl;		
		if(bizInfo.length>160){
			bizInfo = bizTrucName+'\n'+truncAddress+cross_streets+'\n'+phoneStripped+'\n'+bizMUrl;
		}
		if(bizInfo.length>160){			
			if (bizTrucName.length>25){bizTrucName = bizTrucName.substr(0,22)+'...';}
			bizInfo = bizTrucName+'\n'+truncAddress+'\n'+phoneStripped+'\n'+bizMUrl;
		}
		if(!Yelp.userPhone){Yelp.userPhone = '';}
		
		if(!send2phonePop.contents){
		send2phonePop.makePop(aLink,'send2phonePop','<div id="loading_message">Loading...</div>',[0,-230]);
		var params = {'biz_id':json_biz.id,'biz_info':bizInfo,'reply':$H(reply).toQueryString(),'user_phone':Yelp.userPhone};
		params.onComplete = function(){
			//set the character count
			charCountDown(document.send2PhoneForm.send2phone_bizInfo,160);
			//reapply autoPop class to solve IE rendering bug
			Yelp.styleRefresh('send2phonePop','autoPop');
			send2phonePop.contents = $('send2phonePop_inner').innerHTML; //save contents.
		};
		var send2PhoneFill = new Yelp.async_fill('send2phonePop_inner',"/pop_fill/send2Phone",params);
		send2PhoneFill.fetch_contents();
		send2PhoneFill=null;
		}else{
			send2phonePop.makePop(aLink,'send2phonePop',send2phonePop.contents,[0,-230]);
		}
		
		send2phonePop.extraPostVars = 'action_sendsmsjson=1';
		if(reply.method){
			send2phonePop.updaterFunction = function(){
				window.setTimeout("window.location.reload(true);",1800);
			};
		}else{
			send2phonePop.updaterFunction = function(req){
				if(req.savedNumber){
					Yelp.userPhone = req.savedNumber;
				}
			}
		} 
		
	}else{
		send2phonePop.closePop();
	}
}

Yelp.BizReviewsFetcherQuery = Class.create();
Object.extend(Yelp.BizReviewsFetcherQuery.prototype, {
	initialize: function() { 
		// selected review
		this.hrid  = "";
		// featured review 
		this.frid  = "";
		this.biz_id = "";
		this.query = "";
	},
	url: function() {
		var p = {};

		// business id.
		if (this.biz_id != "") {
			p['biz_id'] = this.biz_id;
		}
		
		// search query.
		if (this.query != "") {
			p['query'] = this.query;
		}

		// select review id.
		if (this.hrid != "") {
			p['hrid'] = this.hrid;
		}

		// featured review id, needed so we don't show this review on page 1+N.
		if (this.frid != "") {
			p['frid'] = this.frid;
		}

		var encoded_vars = Yelp.encodeQueryComponents(p);
		return '/biz_details/reviews_snippet?' + encoded_vars;
	}
});

// Query to get the selected review for the page.
Yelp.BizReviewsFetcher = Class.create();
Object.extend(Yelp.BizReviewsFetcher.prototype, { 
	initialize: function() {
		this.current_query = new Yelp.BizReviewsFetcherQuery();
		this.query_counter = 0;
		this.default_feedback = {"funny":false,"useful":false,"cool":false};
	},
	// Parse the fragment variables.
	_parseHashVars : function() {
		var biz_vars = {};
		var curr_url = window.location.href;
		if(curr_url.match('#')&&(curr_url.split('#')[1]!='')){
			biz_vars = Yelp.getHashVars(window.location.href);
		}
		// Get the selected review id.
		if (biz_vars.hrid) {
			this.current_query.hrid = biz_vars.hrid;
		}
		// Get the search query so we can highlight the selected review
		// on the next page (we send this as part of the xhr request).
		if (biz_vars.query) {
			this.current_query.query = biz_vars.query; 
		}
	},

	// this function can create it if it doesn't exist. will add it as the top review inside $('bizReviewsInner')
	_getHighlightedReviewHeader: function(create){
		var header = $('highlightedReviewHeader')
		if(!header && create){
			header = $(document.createElement('h3'))
			Element.update(header, 'Selected Review')
			header.id = 'highlightedReviewHeader'
			$('bizReviews').insertBefore(header, $('bizReviewsInner'))
		}
		return header
	},
	// this function can create it if it doesn't exist. will append it to the end of $('bizReviewsInner')
	_getFavoritesReviewHeader: function(create){
		var header = $('favoritesReviewHeader')
		if(!header && create){
			header = $(document.createElement('h3'))
			var link = document.createElement('a')
			link.href = '/user_details_reviews_favorites'
			Element.update(link, 'Your Favorites')
			Element.update(header, 'Reviews from ')
			header.appendChild(link)
			header.id = 'favoritesReviewHeader'
			$('bizReviewsInner').appendChild(header)
		}
		return header
	},
	// this function can create it if it doesn't exist. will append it to the end of $('bizReviewsInner')
	_getAllReviewHeader: function(create){
		var header = $('allReviewHeader')
		if(!header && create){
			header = $(document.createElement('h3'))
			Element.update(header, 'All Reviews')
			header.id = 'allReviewHeader'
			$('bizReviewsInner').appendChild(header)
		}
		return header
	},

	// don't call this with a review that is already in body.
	// removes review with same id as review in document.
	// review is a prototype Element 
	_removeDuplicate: function(review){
		
		var existing_duplicate_review = $(review.id)
		if(existing_duplicate_review){
			existing_duplicate_review.parentNode.removeChild(existing_duplicate_review)
		}
	},

	// move the currently selected review down
	_moveDownSelectedReview: function(){
		if($('highlightedReviewHeader') && Element.visible($('highlightedReviewHeader'))){
			var highlighted_review = $('highlightedReviewHeader').next()
			if(highlighted_review.hasClassName('review')){
				this._addReviewToInner(highlighted_review)			
				toggleElement('highlightedReviewHeader', false)
			}
		}
	},

	// dynamically add the given review
	// retain_featured_review is a boolean: if true, the featured review stays on top. (such as flow from a search)
	// review_to_add is a prototype Element
	_addReview: function(review_to_add, retain_featured_review){
		var featured_reviews = Element.getElementsByClassName(document.body, 'featuredReview')
		var featured_review = null
		if(featured_reviews.length > 0){
			featured_review = featured_reviews[0]
			if(featured_review.id == review_to_add.id)
				Element.addClassName(review_to_add, 'featuredReview')
		}

		if(retain_featured_review){
			// if the review to add is a featured review AND retain_featured_review, then replace featured review
			// with review_to_add, and get rid of highlighted review if any
			if(Element.hasClassName(review_to_add,'featuredReview')){
				if(featured_review){
					insertAfter(review_to_add, featured_review)
					Element.remove(featured_review)
				}	
				this._moveDownSelectedReview()
				this._redoBizReviewsInnerHeaders()
				return
			}
		}else{
			// if there is a featured review, move it down inside bizReviewsInner and hide the featured review header. 
			if(featured_review){
				featured_review.removeClassName('featuredReview')
				this._addReviewToInner(featured_review)
			}
			toggleElement('featuredReviewHeader', false)
		}
		this._removeDuplicate(review_to_add)
		this._moveDownSelectedReview()
		this._redoBizReviewsInnerHeaders()
		// add the selected review, creating a highlighted review header if necessary
		var highlighted_review_header = this._getHighlightedReviewHeader(true)
		toggleElement(highlighted_review_header, true)
		insertAfter(review_to_add, highlighted_review_header)
	},


	// insert review somewhere appropriately inside bizReviewsInner after removing duplicates. 
	// review_to_add is a prototype Element
	_addReviewToInner: function(review_to_add){
		this._removeDuplicate(review_to_add)

		var favorite_reviews     = $('bizReviewsInner').getElementsByClassName('favoriteReview')
		var non_favorite_reviews = $('bizReviewsInner').getElementsByClassName('nonfavoriteReview')
	
		if(review_to_add.hasClassName('favoriteReview')){
			if(favorite_reviews.length > 0){
				$('bizReviewsInner').insertBefore(review_to_add, favorite_reviews[0])
			}else if(non_favorite_reviews.length != 0){
				$('bizReviewsInner').insertBefore(review_to_add, non_favorite_reviews[0])
			}else{
				$('bizReviewsInner').appendChild(review_to_add)
			}
		}else{
			if(non_favorite_reviews.length > 0){
				$('bizReviewsInner').insertBefore(review_to_add, non_favorite_reviews[0])
			}else{
				$('bizReviewsInner').appendChild(review_to_add)
			}
		}
	},

	// look in bizReviewsInner, and reorganize headers according to number of favorites and nonfavorites 
	_redoBizReviewsInnerHeaders: function(){
		var favorite_reviews     = $('bizReviewsInner').getElementsByClassName('favoriteReview')
		var non_favorite_reviews = $('bizReviewsInner').getElementsByClassName('nonfavoriteReview')
		// create or show favorite header / all header
		if(favorite_reviews.length > 0 && non_favorite_reviews.length > 0){
			var favorite_review_header = this._getFavoritesReviewHeader(true)
			$('bizReviewsInner').insertBefore(favorite_review_header, favorite_reviews[0])
			favorite_review_header.style.display = 'block'
			var all_review_header = this._getAllReviewHeader(true)
			$('bizReviewsInner').insertBefore(all_review_header, non_favorite_reviews[0])
			all_review_header.style.display = 'block'
		}else{
		// hide both favorite and all headers
			toggleElement('favoritesReviewHeader', false)
			toggleElement('allReviewHeader', false)
		}

	},

	// Fetch a selected review id based on the hrid in the fragment.
	_fetcherSuccess: function(resp) {
		var rXML = resp.responseXML.documentElement;
		var snippets = rXML.getElementsByTagName('snippet');
		for (var i = 0; i < snippets.length; i++) { 
			tag_name = snippets[i].getAttribute('name');
			if (tag_name == 'code') { 
				// The code section will hide the review id
				// if it's already in current document
				code = snippets[i].firstChild.nodeValue;
			} else if (tag_name == 'review') {
				review = snippets[i].firstChild.nodeValue;
			} else if (tag_name == 'pager') {
				// Need to replace the pager so we don't show 
				// the selected or featured review in page 1+N.
				pager = snippets[i].firstChild.nodeValue;
			} else if (tag_name == 'empty') {
				// if there was no selected review bail out gracefully.
				return;
			} else { 
				this.fetcherError(resp);
			}
		}

		// Execute the code section of the xml document.
		try {
			eval(code);
		} catch(e) {
			alert(e);
		}

		if(!review){
			return
		}
		// create fetched review
		var fetched_review = document.createElement("div")
		fetched_review.innerHTML = review;
		fetched_review = $(fetched_review).firstDescendant()

		var from_search = (this.current_query.query != '')
		this._addReview(fetched_review, from_search)
		// hack to remove query from future calls to this method
		this.current_query.query = ''
		
		// replace the pager because we need to tell the next 
		// page that we have a selected review (we don't want
		// to show the same review again).
		$('paginationControls').innerHTML = pager;
				
		if(Yelp.review_feedback_handlers[this.current_query.hrid]){
			// reset review feedback buttons
			for(var i = 0; i < Yelp.review_feedback_handlers[this.current_query.hrid].feedback_types.length; i++) {
				if (Yelp.review_feedback_handlers[this.current_query.hrid].setting[Yelp.review_feedback_handlers[this.current_query.hrid].feedback_types[i]]) {
					Yelp.review_feedback_handlers[this.current_query.hrid].set_button_image(Yelp.review_feedback_handlers[this.current_query.hrid].feedback_types[i], 'press');
				}
			}
		}else{
			// review feedback was not already initialized in HTML, so do it now
			if(Yelp.loggedin_userid){
				this.getPrevFeedback();
			}else{
				Yelp.review_feedback_handlers[this.current_query.hrid] = new Yelp.ReviewFeedbackHandler(this.current_query.hrid, this.default_feedback, this.getVotes() );
			}			
		}
	},
	getVotes: function(){
		var types = ['useful','funny','cool'];
		var votes = {};
		for(var i=0;i<types.length;i++){
			var val = $('review_feedback_stats.'+this.current_query.hrid+'.'+types[i]).innerHTML.match(/\d+/gi);
			if(val){
				votes[types[i]] = parseInt(val[0]);
			}else{
				votes[types[i]] = 0;
			}	
		}
		return votes;
	},
	getPrevFeedback: function(){
		(new Ajax.Request('/json_previous_feedback',{
			method:"POST",
			postBody:Yelp.encodeQueryComponents({'hrid':this.current_query.hrid}),
			onSuccess:function(req){
				var reply = req.responseText.evalJSON(true);
				Yelp.review_feedback_handlers[this.current_query.hrid] = new Yelp.ReviewFeedbackHandler(this.current_query.hrid, reply, this.getVotes() );
			}.bind(this),
			onFailure:function(req){
				Yelp.review_feedback_handlers[this.current_query.hrid] = new Yelp.ReviewFeedbackHandler(this.current_query.hrid, this.default_feedback, this.getVotes() );
			}.bind(this)
		}));
	},
	fetcherSuccess: function(query_number, resp) {
		if (query_number != this.query_counter) {
			return; 
		}
		if (resp.responseXML && resp.responseXML.documentElement){
			this._fetcherSuccess(resp);
		} else {
			this.fetcherError(resp);
		}
	},
	fetcherError: function(response) { 
		var error_div = '<div id="error_result"><h3>Biz Review Error</h3><p>Whoops, something went wrong. Please try again, or if the problem persists, please email <a href="mailto:feedback@'+'yelp.com">feedback@'+'yelp.com</a> to report the error.</p></div>'	
		$('snippetReviews').innerHTML=error_div;
	},
	// Get the selected review via xhr.
	fetchReviews: function(biz_id, featured_review_id, FTRid){
		if(!FTRid){var FTRid=false;}
		this.current_query.biz_id = biz_id;
		this.current_query.frid = featured_review_id;
		
		if(FTRid){ //fetching FTR
			this.current_query.hrid = FTRid;
		}else{ //regular hrid request
			this._parseHashVars();
			if (this.current_query.hrid == "") return;
		}
		if(json_biz.review_count==1){ // if there is only 1 review, no need to fetch and change anything except for the header
			// unless there's a featured review...
			if($('featuredReviewHeader') && Element.visible($('featuredReviewHeader'))){
				// do nothin		
			}else{
				this._getHighlightedReviewHeader(true)
				toggleElement('favoritesReviewHeader', false)
				toggleElement('allHeader', false)
			}
		}else{
			this.querycounter++;
			(new Ajax.Request(
			this.current_query.url() + "&nocache="+(new Date()).getTime(), 
			{on404: this.fetcherError.bind(this), 
			onSuccess: this.fetcherSuccess.bind(this, this.query_counter), 
			onFailure: this.fetcherError.bind(this), 
			method:'get'}));
		}
	}
});
Yelp.biz_announce_track = function(click) {
	// Log announcement view
	var clickVal = "0";
	if (click) clickVal = "1";
	new Ajax.Request("/biz_details/track_announce", {parameters: "bid="+json_biz.id+"&aid="+json_biz.biz_announcement.id+"&click=" + clickVal});
};
Yelp.biz_announce = function(id_str){
	this.id_str = id_str;
	this.el = $(id_str);
	this.desc_str = json_biz.biz_announcement.description;
	this.announce_snip = this.el.innerHTML;
	this.start = this.el.offsetHeight;
	this._announce_tracked = false;
	Event.observe($(id_str + '_more'), 'click', this.show_ad.bind(this));
	Event.observe($(id_str + '_less'), 'click', this.hide_ad.bind(this));
	Yelp.biz_announce_track(false);
};
Yelp.biz_announce.prototype.show_ad = function(){
	this.el.innerHTML = this.desc_str;
	this.myHeight = new fx.Height(this.id_str, {duration: 200});
	this.myHeight.scale(this.start);
	$(this.id_str + '_more').hide();
	$(this.id_str + '_less').show();
	
	if (!this._announce_tracked) {
		// Log announcement click
		Yelp.biz_announce_track(true);
		this._announce_tracked = true;
	}
};
Yelp.biz_announce.prototype.hide_ad = function(){
	this.myHeight.scale(this.start);
	setTimeout(this.reset.bind(this),200);	
};
Yelp.biz_announce.prototype.reset = function(){
	this.el.innerHTML = this.announce_snip;
	$(this.id_str + '_less').hide();
	$(this.id_str + '_more').show();
};

// new less functional biz details map
Yelp.biz_details_map = Class.create();
Object.extend(Yelp.biz_details_map.prototype, {
	initialize:function() {
		map = new GMap2(document.getElementById("mapdiv"));
	
		map.addControl(new GSmallZoomControl());
		map.setCenter(new GLatLng(parseFloat(json_biz.latitude), parseFloat(json_biz.longitude)), 15);
	
		var m = createBizMarker(json_biz, -1, false);
		map.addOverlay(m);
		m = null;
		
		copyrightTimer = window.setInterval('makeCopyrightSmaller()', 150);
		Event.observe(window, 'unload', this.unload);
	},
	unload:function(){
		if(map){
			map.clearOverlays.call(map);
			GUnload();
		}
		map = null;
	}
});

Yelp.biz_ratings_graph_init = function(evt){
	var anchor = findEventTarget(evt);
	if(!Yelp.biz_ratings_graph){
		if(!Yelp.popBox){ // if dynObjects isn't loaded, lazyload it.
			Yelp.addScript(jsPrefix+'dynObjects.js','dynObj',[Yelp,'popBox'],function(){
				Yelp.biz_ratings_graph=new Yelp.popBox(); //initialize popup
				Yelp.drawGraphPop(anchor);
			});
		}else{
			Yelp.biz_ratings_graph=new Yelp.popBox(); //initialize popup
			Yelp.drawGraphPop(anchor);
		}
		Event.observe(window,'unload',function(){Yelp.biz_ratings_graph = null;});
	}else{
		Yelp.drawGraphPop(anchor);
	}
};
Yelp.drawGraphPop = function(anchor){
	if(!Yelp.biz_ratings_graph.opened){
		var gp_contents = '<h4 id="bizGraphHeader">Rating Details</h4>'+
		'<div id="histogram"></div> <div id="ratingchart"></div>'+
		'<p id="popFooter"><a href="javascript:Yelp.biz_ratings_graph_close();">Close</a></p>';
		Yelp.biz_ratings_graph.makePop(anchor,'bizGraphPop',gp_contents,[100,0],{'handle':'bizGraphHeader'});
		function _drawCharts(){
			Yelp.createChartSO(json_biz.id, "histogram", "Bar2D.swf", "histogram", "250", "182");
			Yelp.createChartSO(json_biz.id, "ratingchart", "Line.swf", "ratingchart", "250", "225");
		}
		if(!window.deconcept){ // test for SWFObject
			Yelp.addScript(jsPrefix+'swfobject.js','swfJS',[window,'deconcept'],_drawCharts);
		}else{
			_drawCharts();
		}
		if(window.slideshow){ //slideshow effects interfere with graph display. hide it.
			slideshow.pause();
			$('slideViewer').hide();
		}
		//IE6 is mysteriously not setting draggable properly in makePop, so set it here again.
		/*@cc_on
			/*@if (@_jscript_version <= 5.6)
		if(typeof(Draggable)!='undefined'){
			(new Draggable('bizGraphPop',{starteffect:null, endeffect:null, handle:'bizGraphHeader'}));
		}
			/*@end
		@*/
	}else{
		Yelp.biz_ratings_graph_close();
	}
};
Yelp.biz_ratings_graph_close = function(){
	if(window.slideshow){
		$('slideViewer').show();
		slideshow.start();
	}
	Yelp.biz_ratings_graph.closePop();
};
Yelp.createChartSO=function(biz_id, type, swf, div, width, height){
	var so = new SWFObject(Yelp.api_domain+"/Charts/" + swf, type, width, height, "8", "#ffffff");
	so.addVariable("dataURL", Yelp.api_domain+"/biz_graph/" + type + "/" +  biz_id);
	so.addParam("allowScriptAccess", "always");	
	so.write(div);
	return so;
};
Yelp.makeSupporterTooltip=function(){
	var supporterTooltip;
	if ($('bizSupporter')) supporterTooltip = new Yelp.tooltipz('bizSupporter');
};



