//namespace
var ha = {
	ajax: {}, map: {}, geocode: {}, reviews: {}, page: {}, settings: {}, site: {}, strings: {}, ui: {},
	
    seo: {
    	/* business requirement to have markup up high but display down low */
    	showSeoText: function() {
    		// check if the elements exist before calling them - the no search results page and some decorates
    		// do not for instance
    		if ($j('#searchText') && $j('#searchTextPosition')) {
    			$j('#searchTextPosition').append($j('#searchText'));
    		}
    	}
    },
    
    util: {
    	isInt: function(c){ return((c>="0")&&(c<="9")) },
    	
    	initToggles: function(){
			$j(".expand .content").addClass("hidden");
			$j(".expand .show").removeClass("hidden");
			$j(".expand .action").bind("click", function(){
				var el = $j(this).parent("div.container").children("div.content");
				if(el.hasClass("hidden")){
					el.removeClass("hidden");
					$j(this).addClass("open");
				}
				else{
					el.addClass("hidden");
					$j(this).removeClass("open");
				}
			});
		},
		
		initPopupUrls: function(){
			$j(".popup-url").bind("click", function(){
				window.open(this.href);
				return false;
			});
		},	
		
		initSearchSwap: function(){
			$j(".input-keyword").each(function(){
		        var val = $j(this).val();
		        var rel = $j(this).attr("rel");
		        if(val == ""){ 
		        	$j(this).addClass("default");
		        	$j(this).val(rel);
		        }
		        else if(val != rel){
		        	$j(this).removeClass("default");
				}
			});
			$j(".input-keyword").focus(function(){
				var val = $j(this).val();
				$j(this).removeClass("default");	
				if($j(this).attr("rel") == $j(this).val()){
					$j(this).val("");
				}
			});
			$j(".input-keyword").blur(function(){
				var val = $j(this).val();
				$j(this).removeClass("default");
				if($j(this).val() == ""){
					$j(this).addClass("default");
					$j(this).val($j(this).attr("rel"));
				}
			});
		},
		
		// used to get dateformat for the datepicker
		calDateFmt: function() {
			var dateSplit = brand.javaDateInputPattern.split("/");
			return (dateSplit[0].charAt(0) + "-" + dateSplit[1].charAt(1) + "-" + dateSplit[2].charAt(0)).toLowerCase();
		},
		
		//onkeyup: monitor length and update counter
		limiter: function(event){
			var maxChars = $j(this).attr('maxlength');
			var charCount = $j(this).val().length;
			var lineCount = $j(this).val().split(/\r\n|\n|\r\|\f/).length;
			var totalCount = (charCount > 0) ? charCount + lineCount : 0;
			var remainder = ((maxChars - totalCount) > -1) ? maxChars - totalCount : 0;
			var allowedKeys = new Array(8,9,27,46,33,34,35,36,37,38,39,40,45);
						
			if(event.metaKey || event.ctrlKey || event.altKey) return true;
			
			if(jQuery.inArray(event.keyCode, allowedKeys) != -1){
				$j('#remainder').text(remainder);
				return true;
			}
			
			if(totalCount >= maxChars){
				$j(this).val($j(this).val().substr(0,maxChars-lineCount));
				$j('#remainder').text(remainder);
				return false;
			}
			$j('#remainder').text(remainder);
		},
		
    	partialBox: function(partialHeight,duration){
    		$j(".partial-box .toggles").click(function(){
				var contentHeight = $j(this).siblings(".content").children("div").height();
				if (contentHeight > partialHeight){
					if ($j(this).children(".fade").css("display") == "block"){
						$j(this).children(".fade").css("display","none");
						$j(this).siblings(".content").animate({height: contentHeight}, duration);
						var sibling = $j(this).children(".hide");
						var delay = function() { toggle(sibling); };
						setTimeout(delay, duration+1);
					} else {
						$j(this).children(".hide").css("display","none");
						$j(this).siblings(".content").animate({height: partialHeight + "px"}, duration);
						var sibling = $j(this).children(".fade");
						var delay = function() { toggle(sibling); };
						setTimeout(delay, duration+1);
					}
					function toggle(el){ $j(el).css("display","block"); }
				} else {
					$j(this).children(".fade").css("display","none");
					$j(this).children(".all").css("display","block");
				}
    		});
    	}
    }
    
};

/* 
 * Straightforward/simple Observer pattern implementation
 * Example useage:
 * var publisher = new Observer
 * publisher.subscribe(function(msg){
 *    alert(msg);
 * });
 * publisher.fire("Event fired!");
 */
function Observer() {
	this.fns = [];
}

Observer.prototype = {
	subscribe : function(fn) {
		this.fns.push(fn);
	},
	unsubscribe : function(fn) {
		this.fns = this.fns.filter(
			function(el) {
				if (el !== fn) {
					return el;
				}
			}
		);
	},
	fire : function(o, thisObj) {
		var scope = thisObj || window;
		this.fns.forEach(
			function(el) {
				el.call(scope, o);
			}
		);
	}
};
// Add some sugar to the Array prototype
Array.prototype.forEach = function(fn, thisObj) {
    var scope = thisObj || window;
    for ( var i=0, j=this.length; i < j; ++i ) {
        fn.call(scope, this[i], i, this);
    }
};
Array.prototype.filter = function(fn, thisObj) {
    var scope = thisObj || window;
    var a = [];
    for ( var i=0, j=this.length; i < j; ++i ) {
        if ( !fn.call(scope, this[i], i, this) ) {
            continue;
        }
        a.push(this[i]);
    }
    return a;
};

//TO-DO: deprecate these
var jsEnabled = function(s){ this.s=s;}
var commentsLangTxt = function(s){ this.s=s;}

/*
 * GLOBAL
 * advancedSearchForm, homeSearchForm, keywordSearchForm, refineSearchForm (aka sidebar)
 * noResults, 404error, error, secondary pages, etc.
 */
var searchErrorObserver = new Observer;

ha.site.searchform = {
    init: function(){
        
        $j('.input-keyword').keyup(function(e){
        	e = e || window.event;
        	var keyCode = e.keyCode ? e.keyCode : e.which ? e.which : e.charCode;
        	if (keyCode == 13) {
        		ha.site.searchform.submit(e);
        	}
        });
        
    	$j('form[name=searchForm],form[name=refineSearchForm]').each(function(){
    		$j(this).submit(function(e){ return false; });
    		
    		$j('.search-submit-button', $j(this)).click(function(e){
    			ha.site.searchform.submit(e);
    		});
    	});
    	
    	$j("#price-range-fields .input").bind("focus", function(){
    		$j("#price-range-vaidation").addClass("hidden").css("display", "");
    	});
    	
    },

    isDigit: function(e){
    	var charCode = (e.which) ? e.which : window.event ? window.event.keyCode : 0;
   		if (charCode > 31 && (charCode < 48 || charCode > 57)){
   			return false;
   		}
   		return true;
    },
    
    submit: function(e){
    	var formObj = $j('form[name=searchForm],form[name=refineSearchForm]');
    	if (e) formObj = $j(e.target).parents('form');

    	// determine what sort of search has been performed
    	var searchType = formObj.attr("id");
    	if(searchType == "simple-search") searchType = "simple";
    	else if(searchType == "keywordSearchForm") searchType = "keyword";
    	else if(searchType == "adv-search-form") searchType = "advanced";
    	else if(searchType == "refineSearchform") searchType = "availability";
    	else searchType = "notknown";
    	
    	$j.cookie('searchType', searchType, {expires: 1, path: '/'});	

    	// get keywords
    	var keywords = ($j("input[name=keywords]", formObj).length > -1) ? $j("input[name=keywords]", formObj).val() : "";
    	var defaultMessage = $j("input[rel]", formObj).attr("rel");

    	if ($j.trim(keywords) !="" && keywords!=defaultMessage) {
    		if(searchType == "availability"){
    			// avoid double encoding
        		keywords = "/keywords:" + keywords;
    		}
    		else{
        		keywords = "/keywords:" + encodeURIComponent(keywords);
    		}
    	}
    	else{
    		keywords = "";
    	}

    	var refinements = "";
    	if ($j("#refinements",formObj).val() != null && $j.trim($j("#refinements",formObj).val()) != ''){
    		// get refineSearchForm refinements aka sidebar
    		refinements += $j("#refinements",formObj).val().replace("+", "*");
    	}
    	else{
    		// get advancedSearchForm refinements
    		var refinements = "";
    		$j('input, select',formObj).each(function(i,el){
    			if ((el.type == "select-one" && el.value != '') || (el.type == "checkbox" && el.checked)){
    				refinements += '/' + el.value;
    			}
    		});
    	}

    	// validate price range        	
    	var priceFrom = $j("#priceFrom").val(); 
    	var priceTo = $j("#priceTo").val();
    	var prices = "";

    	if(priceFrom !=null && priceTo != null && parseInt(priceFrom) > parseInt(priceTo)){
    		searchErrorObserver.fire();
    		$j("#price-range-vaidation").fadeIn("def");
    		return false;
    	}
    	//Were prices provided?
    	if(priceFrom !=null && priceFrom > 0){
    		prices += "/minPrice/" + priceFrom;
    	}
    	if (priceTo !=null && priceTo > 0) {
    		prices += "/maxPrice/" + priceTo;
    	}
    	//If prices provided, add currency 
    	if((priceFrom !=null && priceFrom > 0) || (priceTo !=null && priceTo > 0)) {
    		prices += "/currency/" + brand.baseCurrency;
    	}
    	
    	// if a startDate was not entered then set it to the end date
    	if (searchType != "keyword") {
    		ha.util.datePickControl.checkStart('startDateInput','endDateInput');
    	}
    	
    	var url = '/search';
    	if (refinements != ''){ url += '/refined'; }
    	url += keywords;
    	url += refinements;
    	url += ha.site.searchform.dateParam($j('#startDateInput', formObj),'arrival');
    	url += ha.site.searchform.dateParam($j('#endDateInput', formObj),'departure');
    	url += prices;
    	window.location = url;
    },
    
    // return a formatted url param for a given search date string
    dateParam: function(o,s){
    	if ((typeof $j(o).val() == "undefined") || (ha.site.searchform.delim($j(o).val()) == "")){
    		return "";
    	}
    	else if ($j(o).val() != brand.dateInputHelpText){
    		if (brand.dateInputHelpText == 'mm/dd/yyyy'){
    			var parts = $j(o).val().split("/")
    			return '/' + s + ':' + parts[2] + '-' + parts[0] + '-' + parts[1];
    		}
    		return '/' + s + ':' + $j(o).val().split("/").reverse().join("-");
    	}
    	return "";
    },
    
    // set the date string delimiters
    delim: function(s){
		if(s.indexOf("/") == -1){
			if(s.indexOf("-") > -1) s = s.replace(/-/g, "/");
			else if(s.indexOf(".") > -1) s = s.replace(/\./g, "/");
			else s = "";
		}
		return s;
    }
};

/*
 * HOME PAGE
 */
var homeBannerUrl2 = function(s){ this.s=s;}
var homeBannerUrl3 = function(s){ this.s=s;}
ha.page.home = {
	init: function(){
		ha.util.initToggles();
		if (homeBannerUrl2.s || homeBannerUrl3.s) ha.page.home.initSwapImages();
	},
	initSwapImages: function(){
		var swapduration = 8000;
		var timeout;

		$j("#layer2 img").attr("src", homeBannerUrl2.s);
		$j("#layer3 img").attr("src", homeBannerUrl3.s);
		
		$j(window).load(function(){
		
			$j("#layer2 img, #layer3 img").show();
			// fix text dimming in Firefox
			// http://allinthehead.com/retro/328/when-bugs-collide-fixing-text-dimming-in-firefox-2
	
			function show() {
				$j('#layer1').fadeIn(1500)
				setTimeout(function(){
					$j('#layer2').css({display:'block'});
				}, 1501);
				timeout = setTimeout(hideOne, swapduration);
			}
			function hideOne(){
				$j('#layer1').fadeOut(1500);
				timeout = setTimeout(hideTwo, swapduration);
			}
			function hideTwo(){
				$j('#layer2').fadeOut(1500);
				timeout = setTimeout(show, swapduration);
			}
			
			timeout = setTimeout(hideOne, swapduration);

		}); 
	}
};

/*
 * SEARCH PAGE
 */
ha.page.search = {
	init: function(){
		$j.cookie('newSort', null);
		
		$j("#sortingSelect").change(function(){
			ha.page.search.onSortChange();
		});
		
		if($j("#fullAdsFirst")) {
			$j("#fullAdsFirst").change(function(){
				ha.page.search.onFullAdsFirstChange();
			});
		}
		
		// set up Omniture events
		ha.page.search.setOmnitureEvents();
		ha.util.initToggles();
		ha.page.search.initCollapsableRegions();
		ha.page.search.initPriceToggle();
		ha.page.search.initReviewsRefinement();
		ha.page.search.initSnippets(5, 30);
		ha.page.search.initAttractions();
		ha.seo.showSeoText();
		
    },

	/**
	* This method is tied to the select box 'sortingSelect'.  When its state changes, 
	* this method will change the current page's URL to the destination in the sort select. 
	**/
	onSortChange: function(){
	    // find the select
		select = document.getElementById("sortingSelect");
		
		// grab the destination string
		destination = select[select.selectedIndex].value;
			
		// if it exists (i.e. is not the "Select One:" option
		if (destination) {
			//null expires deletes cookie at browser exists
			if ($j.cookie('orderByOffer') != null) {
				$j.cookie('orderByOffer', null, {path: '/'});
			}
			$j.cookie('orderBy', destination, {path: '/'});
			$j.cookie('searchType', "newsort", {expires: 1, path: '/'});
			// then go there
			ha.page.search.doSort();
		}
	},
	
	/**
	* This method is tied to the checkbox for showing properties with images first
	**/
	onFullAdsFirstChange: function() {
	    checkbox = document.getElementById("fullAdsFirst");	    
	    $j.cookie('fullAdsFirst', null, {path: '/'}); // This ensures that non-session cookies are deleted
		$j.cookie('fullAdsFirst', checkbox.checked, {path: '/'});
		ha.page.search.doSort();	    
	},

	/**
	 * Sets the page size via a cookie.
	 */
	doSetPageSize: function(pageSizeSelect){
		var newPageSize = Number(pageSizeSelect.options[pageSizeSelect.selectedIndex].text);
			
		$j.cookie('pageSize', newPageSize, {expires: 7, path: '/'});
		ha.page.search.doSort();
	},
	
	doSort: function(){
		$j.cookie('newSort', 1);
		window.location = window.location;
	},
	
	setOmnitureEvents: function(){
		$j("#sidebarContent ul.criteria ul.criteria li").bind("click", function(event){
			$j.cookie('searchType', "refinement:" + $j(this).attr("id"), {expires: 1, path: '/'});
		});
	},
	
	initPriceToggle: function(){
		var priceValues = ($j('#priceFrom.input').val() + $j('#priceTo.input').val());
		if (priceValues > 0) {
			$j("#price-range .action").addClass("open");
			$j("#price-range .content").removeClass("hidden");
			$j("#findByDateButton").insertAfter("#price-range-fields");
		}

		$j("#price-range .action").bind("click", function(){
			if($j(this).hasClass("open")){
				$j("#findByDateButton").insertAfter("#price-range-fields");
				$j("#priceFrom").focus();
			}
			else{
				$j("#findByDateButton").insertAfter("#findByDateForm");
	    		$j("#price-range-vaidation").addClass("hidden").css("display", "");
				$j("#price-range-fields input").val("");
			}
		});
	},
	
	initSnippets: function(yOff,xOff) {
        $j('.reviews-popup').each(function(n, popup) {
        	var popupid = '#'+popup.id;
        	var ratingdivid = popupid.replace('-snippet-','-read-') + " .read-count";
        	popup = $j(popupid);
        	var popupheight = popup.height();
    		var cssValues = {"top" : (yOff - popupheight) + "px",
    			"left" : xOff + "px"};
        	$j(ratingdivid).hover( function() { // over function
        		popup.css(cssValues).fadeIn(200);
        	},
        	function() { // out function
        		popup.fadeOut(100);
        	});
        });
	},
	
	initCollapsableRegions: function(){
		$j("body.consolidated-region ul.criteria li ul.region > li").each(function(){
			// only apply the event to regions which have child nodes to display
			if($j(this).find("ul.children").size() > 0){
				$j(this).addClass("parent");
				$j(this).click(function(event){
					var target = $j(event.target);
					if(target.attr("tagName") == "A"){
						return true;
					}
					if(target.hasClass("parent")){
						target.toggleClass("open");
					}
				});
			}
		});

	},
	
	initReviewsRefinement: function(){
		$j("input[name=review_count_refinement]").change(function(){
			document.location = $j(this).val();
		});
	},
	
	initAttractions: function(){
		$j("#attractions-lnk").click(function(){ 
			$j.cookie('ha-search-url', document.location, {path: '/'});
		});
	}
};

/*
 * LANDING PAGE
 */ 
ha.page.landing = {
	init: function(){
		if ($j("#mapLink").length > 0){
			$j("#mapLink").click(function(){
				ha.page.landing.showMap();
			});
		}else if ($j("#map").length > 0){
			$j("#map").css("display","block");
		}
		$j(".zero-features a.headerLink").click(function(){
			return false;
		});
		ha.page.landing.seoCoulmn();
		ha.seo.showSeoText();

	},
		
	showMap: function showMap(){
		if($j("#mapTxt").html() == ha.strings.viewMapMsg) {
			$j("#mapTxt").html(ha.strings.closeMapMsg);
				
			$j("#map").css({display:"block", backgroundColor:"#fff", borderColor:"#fff", textAlign:"center"});	
			$j("#regionMapImage").css({margin:"10px"});
		} else {
			$j("#map").css({display:"none"});
			$j("#mapTxt").html(ha.strings.viewMapMsg);
		}
	},
	
	seoCoulmn: function(){
		/* Show and Hide seo content on right column of landing page */

		$j(document).ready(function(){
			var h = $j("#searchText").height();
			if(h >= 300) {
				$j("#searchText").addClass("closed-seo");
				$j("#fade span").click(function(){
					$j('#searchText').removeClass("closed-seo");
				});
				$j("#hideSeo").click(function(){
					$j('#searchText').addClass("closed-seo");
				});
			}
			else{ 
				$j("#hideSeo").css("display","none");
			};
		});		
	}
};

/*
 * ADVANCED SEARCH
 */
ha.page.advancedSearch = {
	init: function(){
		$j('#refinementsContent0, #refinementsContent1, #refinementsContent2').hide();
		if ($j("#keywords").val()){
			document.searchForm.keywords.focus();
		}
		
		searchErrorObserver.subscribe(function(){
			//scroll into view
	        $j('html,body').animate({scrollTop: $j("#price-range-fields").offset().top}, 500);
		});
		ha.util.initToggles();
	}
};

/*
 * PROPERTY DETAILS
 */
ha.reviews = {
	voteHelpful: function(reviewId, helpful) {
		
		if(ha.page.property.notVoted(reviewId)) {
			$j.ajax({ 
				type: "GET", 
				url: "/vacation-rental/reviews/vote", 
				data: ({helpful : helpful, reviewId: reviewId}),
				dataType: "xml",
	  	        success:function(data){ 
				 	helpful = $j(data).find('helpful').text();
				 	total = $j(data).find('total').text();
		
				 	ha.page.property.updateVotes(reviewId, helpful, total, true);
				}, 
				error:function(xhr,err,e){ alert( "Error: " + err ); }
			});
		}
	}
}

ha.page.property = {
    init: function(){
		ha.ui.modalbox.init();
		ha.page.property.initNavBar();
		ha.ajax.inquiry.init();
		if (ha.settings.similarPropertiesOn){
			ha.util.initToggles();
		}
		
		if(window.ie6) { 
        	// get the image tag
        	image = $j('#regionMapImage');
        	if(image) {
        		imageSourceUrl = image.srcsure
        		image.src="";
        		image.src=imageSourceUrl;
        	}
        }
	},
	
	initNavBar: function(){
		var anchors = new Array('photos','location','rates','amenities');
		for (var i=0; i< anchors.length; i++){
			if ($j('#'+anchors[i]+'-bar').length == 0 || $j('#'+anchors[i]+'-bar').css("display") == "none"){
				$j('.'+anchors[i]+'-link').css("display","none");
			}
		}
	}
};

/*
 * WRITE REVIEW PAGE
 */ 
ha.page.writeReview = {
	init: function(){
		$j('#body').keyup(ha.util.limiter);
		if($j('#body').val() == ""){
			$j('#remainder').text($j('#body').attr("maxlength"));
		}
		else{
			$j('#body').change(ha.util.limiter).change();
		}  
		
		$j("#ratings label").click(function(){
			$j("#ratings label").removeClass("checked");
			backgroundPositon = $j(this).attr("for").substr($j(this).attr("for").length-1) * 71;
			$j("#ratings").css("background-position",  "0 -" + backgroundPositon + "px" );
			$j("#" + $j(this).attr("for")).attr("checked", "checked");
			$j(this).addClass("checked");
		});
		
		$j("#ratings label input[checked]").parent().triggerHandler("click");
		
	}
};

/*
 * ATTRACTIONS PAGE
 */

$j(document).ready(function(){
	//global
	ha.site.searchform.init();
	$j.cookie('searchType', null, {path: '/'});	 //clear search type cookie
	
	// init pop-up url's
	ha.util.initPopupUrls();

	if ($j("body.homePage").length > 0) ha.page.home.init();
	else if ($j("body.search-page").length > 0) ha.page.search.init();
	else if ($j("body.landing").length > 0) ha.page.landing.init();
	else if ($j("body.adv-search").length > 0) ha.page.advancedSearch.init();
	else if ($j("body.property").length > 0) ha.page.property.init();
	else if ($j("body.attractions.review-add").length > 0 || $j("body.attractions.review-write").length > 0 || $j("body.reviews-write").length > 0 || $j("body.review-response-write").length > 0 || $j("body.report-abuse").length > 0) ha.page.writeReview.init();
	else if ($j("body.attractions.overview").length > 0) ha.util.partialBox(200,800);
	
	// load iframes - ads, tracking pixels, google maps
	$j("iframe[rel]").each(function(){
		$j(this).attr("src", $j(this).attr("rel"));
	});
	
	if ($j("body.attractions").length > 0) {
		ha.page.attractions.init();
	}
});


