﻿/**
 * static object that handles page logic
 * @class
 * @constructor
 * @param {jQuery} $ Reference to the jQuery object
 */
var SearchMain = function($) {

	var config = {

		/**
		* maximum number of reviews to show initially
		* @private
		*/
		maxReviews: 10,

		/**
		* maximum number of tips to show initially
		* @private
		*/
		maxTips: 10,

		/**
		* jquery reference of the favorites button html object
		* @private
		*/
		favoriteTrigger: ".favorite"
	};

	/**
	* @namespace Private methods and variables
	*/
	var priv = {
		freeTextInputElement: "#text-search input",
		freeTextSubmitElement: "#text-search .submitbutton",

		/**
		* Container object, holding references to the lightboxes that have been initialized in this page.
		* Using this each lightbox only has to be instantiated once, when it is first called.
		* @type {Lightbox}
		* @private
		*/
		lightboxes: {},

		/**
		* Generic way to open a new lightbox: the contents of the container identified by the supplied id
		* are loaded in a lightbox. Also, the lightbox is cached and thus only has to be initialized once.
		* @param {String} id The id of the container to show in the lightbox
		* @param {Object} options (Optional) Several options can be supplied to override default behavior of just
		* loading the contents of the container. When supplied, these options will be used to initialize the lightbox.
		* @private
		*/
		openLightbox: function(id, options) {
			if (typeof (options) == 'undefined' || !options) {
				options = { container: document.getElementById(id) };
			}
			var lightbox = Lightbox.CreateCached(id, options);
			lightbox.Show();
		},

		/**
		* Show the element matching the supplied ID in a lightbox. Used on the offers page.
		* @param {HTMLElement} anchor The anchor element referencing the popup contents.
		* @param {String} id The id of the popup container
		* @return {Boolean} Returns false to allow event handlers to easily stop default browser behavior
		* @private
		*/
		showOfferInfoInLightbox: function(anchor, id) {
			priv.openLightbox(id, {
				container: document.getElementById(id),
				contentUrl: $(anchor).attr('href'),
				width: '500px'
			});
			return false;
		},

		/**
		* Bind general events for this page
		* @private
		*/
		bindEvents: function() {
			if (location.href.indexOf('personal=') != -1) {
				$('body').addClass('search-personal');
				priv.setCompareChecked();
			} else {
				priv.bindTextSearch();
			}
			priv.bindHighlightRefinements();
			priv.bindShowOccupancyPopup();
			priv.bindMoreInfoEvents();
			if ($('body').attr('class').indexOf('search-offers') > -1) {
				priv.bindQuestionPopups();
			}

			priv.bindFavoritesAndViewedEvents();
		},

		/**
		* Bind events on the links to questions popups, both in the left sidebar and in the main content area.
		* @private
		*/
		bindQuestionPopups: function() {
			// add container for question popups
			$('body').append("<div id=\"questionPopup\"></div>");

			// Bind methods to show popups for questions in left sidebar
			$("#questions-left ul.questions li a").not(".more-questions").bind('click', function() {
				var $anchor = $(this);
				var options = {
					container: document.getElementById("questionPopup"),
					literal: false,
					title: $anchor.text(),
					contentUrl: $anchor.attr('href'),
					width: '643px'
				};
				var lightbox = Lightbox.CreateCached($anchor.attr('href'), options);
				lightbox.Show();
				return false;
			});

			// Open faq in new window
			$("#questions-left ul.questions li a.more-questions").bind('click', function() {
				Utils.newWindow(this, 800, 640);
				return false;
			});
		},

		/**
		* Bind events for showing popups with more information about departures
		* @private
		*/
		bindMoreInfoEvents: function() {
			$("body").append("<div id=\"offersDepartureUnknownPopup\"></div>");
			$("body").append("<div id=\"offersDepartureKnownPopup\"></div>");

			$('a.moreinfo').bind("click", function() {
				return priv.showOfferInfoInLightbox(this, "offersDepartureUnknownPopup");
			});
			$('a.moreinfounknown').bind("click", function() {
				return priv.showOfferInfoInLightbox(this, "offersDepartureKnownPopup");
			});
		},

		/**
		* Bind tooltips to the location selection in the left sidebar. Hovering over a country, region or city
		* will show a tooltip with some additional information.
		* @private
		*/
		bindLocationInfoEvents: function() {
			var path = Resource.GetText("path_prefix");
			var ttOptions = {
				trigger: "hover",
				autoClose: true,
				source: "ajax",
				type: "GET",
				loadingText: "",
				loadingImg: path + "/images/ajax-loader-smallest.gif",
				url: path + "/_html/location-block.aspx"
			};

			var locations = ["country", "region", "city"];
			for (var i = 0; i < locations.length; i++) {
				$("a." + locations[i]).each(function() {
					var $this = $(this);
					ttOptions["data"] = "theme=" + locations[i] + "&id=" + $this.attr("rel");
					$this.jHelperTip(ttOptions);
				});
			}
		},

		/**
		* 
		* @private
		*/
		setCompareChecked: function() {
			var checkIds = $.query.get("id");
			if (checkIds != "" && checkIds.indexOf(",") != -1) {
				checkIds = checkIds.split(",");

				$('div.compareCheck').each(
                    function(i) {
                    	var id = $(this).attr("id").substring($(this).attr("id").indexOf("_") + 1);
                    	for (j = 0; j < checkIds.length; j++) {
                    		if (id == checkIds[j]) {
                    			$(this).addClass("checked");
                    			break;
                    		}
                    	}
                    }
                );
			}
		},

		/**
		* Highlight refinements when hovering in ribbon
		* @private
		*/
		bindHighlightRefinements: function() {
			$('#btnHighlight').hover(function() {
				$('div.navigation-refine').css({
					backgroundColor: '#fffbc3',
					border: 'solid 1px #FF2200'
				});
			}, function() {
				$('div.navigation-refine').css({
					backgroundColor: '#fff',
					border: 'solid 1px #FFF'
				});
			});
		},

		/**
		* Show occupancy popup, when clicking on block in ribbon
		* @private
		*/
		bindShowOccupancyPopup: function() {
			$('#btnTipOccupancy').bind('click', Occupancy.showTravelersPopup);
		},

		/**
		* bind free text search action
		* @private
		*/
		bindTextSearch: function() {
			if ($(priv.freeTextInputElement).length) {
				$(priv.freeTextSubmitElement).bind("click", priv.textSearch);
				if ($(priv.freeTextInputElement).val() != Resource.GetText('search_free_text')) {
					$(priv.freeTextSubmitElement).get(0).disabled = false;
				}
				$(priv.freeTextInputElement).bind("focus", function() {
					$(priv.freeTextSubmitElement).get(0).disabled = false;
					if (this.value == Resource.GetText('search_free_text')) {
						this.value = '';
					}
					else {
						this.select();
					}
				});
				$(priv.freeTextInputElement).bind("keydown", function(evt) {
					if (evt.keyCode == 13) {
						priv.textSearch();
					}
				});

				// autocomplete functionality
				$(priv.freeTextInputElement).autocomplete(Resource.GetText('path_prefix') + "/js/ajax/get_searchsuggestions.ashx", {
					selectFirst: false,
					delay: 10,
                	width: 147,
					matchSubset: false
				}).result(function(event, item) {
					priv.textSearch();
				});
			}
		},

		/**
		* Redirects the page with the correct free text search parameter
		* @private
		*/
		textSearch: function() {
			$input = $(priv.freeTextInputElement);
			if ($input.val() != '' && $input.val() != Resource.GetText('search_free_text')) {
				document.location.href = document.location.pathname + "?searchtext=" + encodeURI($input.attr("value"));
			}
		},

		/**
		* @private
		*/
		buildDepartureCalendar: function() {
			$('div.result-selected .remove').each(function(i) {
				if (this.href.indexOf('daterange=-1') != -1) {
					this.href = 'javascript:void(0);';
					$(this).click(function() {
						SearchMain.changeDateRange('-1');
					});
				}
			});

			// get the number of days to select before and after the selected date
			var daterange = $.query.get('daterange').toString();
			var addDays = 3;
			if (daterange == '1') {
				addDays = 0;
			}
			else if (daterange == '2') {
				addDays = 3;
			} else if (daterange == '3') {
				addDays = 7;
			} else if (daterange == '-1') {
				SearchMain.changeDateRange();
			}

			// get the selected date and get the mindate and maxdate in the range
			var curMinDate = 0;
			var curMaxDate = 0;
			var curSelDate = $.query.get('seldate').toString();
			if (curSelDate != '') {
				var dtCurSelDate = Date.fromString(curSelDate.substring(6, 8) + '/' + curSelDate.substring(4, 6) + '/' + curSelDate.substring(0, 4));
				curMinDate = parseInt(dtCurSelDate.addDays(addDays * -1).asString2());
				curMaxDate = parseInt(dtCurSelDate.addDays(addDays * 2).asString2());
			}
			// build the departure calendar
			$('#start-date').datePicker({
				inline: true,
				createButton: false,
				showYearNavigation: false,
				year: curYear,
				month: curMonth,
				startDate: firstDate,
				endDate: lastDate,
				renderCallback: function($td, thisDate, month, year) {
					// set the dates selected inside the range
					if (thisDate.asString2() == curSelDate) {
						$td.addClass('selected');
						$td.addClass('click');
					} else if (thisDate.asString2() >= curMinDate && thisDate.asString2() <= curMaxDate) {
						$td.addClass('selected');
					}

					// disable the dates the aren't departuredays
					if (departDates['d' + thisDate.asString2()] == null ||
                            departDates['d' + thisDate.asString2()] == '') {
						$td.addClass('disabled');
					}
				}
			});

			// bind the action when a date is clicked
			$('#start-date').bind('dateSelected', function(e, selectedDate, $td) {
				if (daterange == '-1') {
					$('select.daterange').val('2');
				}

				// get the selected daterange
				var minDate = parseInt(selectedDate.addDays(addDays * -1).asString2());
				var maxDate = parseInt(selectedDate.addDays(addDays * 2).asString2());
				selectedDate = selectedDate.addDays(addDays * -1);

				var selectQuery = '';
				var selNValues = '';
				// loop through the date range and build the string with the nvalues to select
				// - and build the string with all the querystrings
				for (var i = minDate; i <= maxDate; i++) {
					if (departDates['d' + i] != null && departDates['d' + i] != '') {
						var queryString = departDates['d' + i].split(',')[1];
						var nValue = departDates['d' + i].split(',')[2];
						selNValues += selNValues == '' ? nValue : '+' + nValue;

						var startIndex = queryString.indexOf('N=');
						if (startIndex != -1) {
							var endIndex = queryString.indexOf('&', startIndex);
							if (endIndex == -1) {
								endIndex = queryString.length + 1;
							}
							selectQuery += '||' + queryString.substring(startIndex + 2, endIndex).replace(/\+/g, '||');
						}
					}
				}
				selectQuery += '|';

				// remove the departuredays nvalues, so only the other nvalues are left over
				for (var key in departDates) {
					var nValue2 = departDates[key].split(',')[2];
					if (selectQuery.indexOf('|' + nValue2 + '|') != -1) {
						selectQuery = selectQuery.replace(new RegExp('/|' + nValue2 + '|/', 'g'), '');
					}
				}

				// combine the to selected departuredays nvalues with the other selected nvalues
				var splitOtherNvalues = selectQuery.split('|');
				for (var j = 0; j < splitOtherNvalues.length; j++) {
					if (splitOtherNvalues[j] != '' && ('+' + selNValues + '+').indexOf('+' + splitOtherNvalues[j] + '+') == -1) {
						selNValues += '+' + splitOtherNvalues[j];
					}
				}

				// submit the selected date range
				var newUrl = $.query.SET('N', selNValues).SET('seldate', selectedDate.asString2()).REMOVE('No');
				location.href = decodeURIComponent(newUrl.toString());
			});
		},

		/**
		* @private
		*/
		buildCalendar: function() {
			if ($('a.btnSelectDate').length) {
				$('a.btnSelectDate,a.btnSelectDateAnimate').bind('click', function(e) {
					$('a.btnSelectDate').css({
						color: '#ccc'
					});
					if ($(this).attr('class').indexOf('Animate') != -1) {
						var offsetAnimate = $('a.btnSelectDateAnimate').offset();
						var oldTop = offsetAnimate.top + 12;
						var oldLeft = offsetAnimate.left;
						$('#calendarContainer').css({
							"top": (oldTop) + "px",
							"left": (oldLeft) + "px"
						});
						var offsetCalendar = $('a.btnSelectDate').offset();
						var newTop = offsetCalendar.top + 12;
						var newLeft = offsetCalendar.left + ($('a.btnSelectDate').width() - 15);
						$('#calendarContainer').animate({
							"top": newTop + "px"
						}, {
							duration: 300
						}).animate({
							"left": newLeft + "px"
						}, {
							duration: 600
						});
					}
					if (reloadDates == 'True') {
						$('#start-date').css({
							'height': '154px',
							'width': '157px'
						});
						$('#start-date').html('');
						var type = 'type=search&';
						if (Resource.GetText('isofferspage') == 'true') {
							type = 'type=offers&';
						}
						$.getJSON(Resource.GetText('path_prefix') + '/js/ajax/departure-dates.aspx', type + location.href.split('?')[1], function(data) {
							firstDate = data.firstDate;
							lastDate = data.lastDate;
							departDates = data.departDates;
							priv.buildDepartureCalendar();
						});
						reloadDates = 'False';
					}
				}).jHelperTip({
					trigger: "click",
					dC: "#date-popup",
					ttC: "#calendarContainer",
					initializeOnce: true,
					autoClose: true
				});
			}
			if (typeof (curYear) != "undefined") {
				priv.buildDepartureCalendar();
			}
		},

		/**
		* Binds the events, sets the classes for the personal item logic
		* makes sure to update the alreadyviewed list, and adds logic to the favorites button
		* @private
		*/
		personalItemsLogic: function() {
			//bind event to the page load, to update the "alreadyviewed" items
			$(window).bind("load",
                function() {
                	PersonalItems.ShowItemLinks();

                	//TODO (Koen): UPDATE THE FAVORITE LINKS TO WHAT IS AVAILABLE IN THE FAVORITES COOKIE
                }
            );

			//bind the click event for the trigger
			$(config.favoriteTrigger).bind("click",
                function(evt) {
                	Log.Debug(config.favoriteTrigger);
                	var accoId = $(this).attr("rel").replace('id', '');

                	//check for add or removal of the favo
                	if (!$(this).hasClass("is-favorite")) {
                		$(this).addClass("is-favorite");
                		$(this).html(Resource.GetText('ACCOMMODATION_IS_FAVORITE'));
                		PersonalItems.Add("favorites", accoId);

                		//update the personal item links
                		PersonalItems.ShowItemLinks();
                	}
                	else {
                		$(this).removeClass("is-favorite");
                		$(this).html(Resource.GetText('ACCOMMODATION_ADD_FAVORITE'));
                		PersonalItems.Remove("favorites", accoId);
                	}

                	// Update the saved accommodations
                	$('#favourite-and-viewed .tabs li.selected').removeClass('selected').trigger('click').addClass('selected');

                	//prevent event bubbling
                	return false;
                }
            );
		},

		bindFavoritesAndViewedEvents: function() {

			//Load accommodation content
			$('#favourite-and-viewed .content').change(function(ev) {
				$(this).load(Resource.GetText("path_prefix") + '/_search/GetPersonalAccommodations.aspx?max=5&personal=' + $(this).attr('rel').toString(),
	                function() {
	                	//remove loader
	                	$(this).removeClass('loading');

	                	//click on acco and goto accommodation page
	                	$('#favourite-and-viewed .content div.acco').click(function() {
	                		document.location.href = $(this).attr('rel');
	                		return false;
	                	});
	                	//click on save-button and put accommodation in favourits
	                	$('#favourite-and-viewed .content div.acco .save-button').click(function() {
	                		var accoId = $(this).attr('rel');
	                		PersonalItems.Add("favorites", accoId);

	                		//remove favourite from result-list
	                		$('#result-list .favorite[rel=id' + accoId + ']').triggerHandler('click');

	                		$(this).css({ display: 'none' });
	                		$('.is-favorite', $(this).parent()).css({ display: 'block' });
	                		$('.delete-button', $(this).parent()).css({ display: 'block' });
	                		return false;
	                	});

	                	//click on delete-button and remove accommodation from favourites
	                	$('#favourite-and-viewed .content div.acco .delete-button').click(function() {
	                		//remove from cookie
	                		var accoId = $(this).attr('rel');
	                		PersonalItems.Remove("favorites", accoId);

	                		// Update the personal items links
	                		PersonalItems.ShowItemLinks();

	                		//remove favourite from result-list
	                		$('#result-list .is-favorite[rel=id' + accoId + ']').triggerHandler('click');

	                		//change html states
	                		if ($(this).parent().parent().attr('rel').toString() == 'alreadyviewed') {
	                			//remove delete button
	                			$(this).css({ display: 'none' });
	                			//add save-button
	                			$('.save-button', $(this).parent()).css({ display: 'block' });
	                			$('.is-favorite', $(this).parent()).css({ display: 'none' });
	                			return false;
	                		}
	                		else {

	                			$('#favourite-and-viewed .content').trigger('change');
	                			return false;
	                		}
	                	});
	                });
			});
		},

		/**
		* Initializes the favorites and already viewed acco's
		* @private
		*/
		initializeFavoritesAndViewed: function() {
			$('#favourite-and-viewed .tabs li').click(function() {

				if (!$(this).hasClass('selected')) {
					$('#favourite-and-viewed .tabs li').removeClass('selected');
					$(this).addClass('selected');
					$('#favourite-and-viewed .content').attr('rel', $(this).attr('id'));
					$('#favourite-and-viewed .content').empty().addClass('loading');
					$('#favourite-and-viewed .content').triggerHandler('change');
				}
				return false;
			});

			//load accommodations for first time
			$('#favourite-and-viewed .tabs li.selected').removeClass('selected').trigger('click').addClass('selected');
		}
	};

	/** @scope SearchMain */
	return {

		changeDateRange: function(parDaterange) {
			if (reloadDates == 'True') {
				var type = 'type=search&';
                if (Resource.GetText('isofferspage') == 'true') {
                    type = 'type=offers&';
                }
				$.getJSON(Resource.GetText('path_prefix') + '/js/ajax/departure-dates.aspx?' + type + location.href.split('?')[1], function(data) {
					firstDate = data.firstDate;
					lastDate = data.lastDate;
					departDates = data.departDates;
					SearchMain.doChangeDateRange(parDaterange);
				});
				reloadDates = 'False';
			} else {
				SearchMain.doChangeDateRange(parDaterange);
			}
		},

		doChangeDateRange: function(parDaterange, reloadDates) {
			var daterangeVal = parDaterange;
			if (daterangeVal == null)
				daterangeVal = $('select.daterange').val();
			var nValues = $.query.get('N').toString();
			if (daterangeVal == '-1') {
				location.href = location.href.split('?')[0] + SearchMain.getQueryStringWithoutDates();
			} else {
				if (location.href.indexOf('?') == -1) {
					location.href = location.href + '?daterange=' + daterangeVal;
				} else {
					var curSelDate = $.query.get('seldate').toString();
					if (curSelDate != '' && nValues != '') {
						var addDays = 0;
						if (daterangeVal == '2') {
							addDays = 3;
						} else if (daterangeVal == '3') {
							addDays = 7;
						}
						// get the selected date and get the mindate and maxdate in the range
						var minDate = 0;
						var maxDate = 0;
						if (curSelDate != '') {
							var dtCurSelDate = Date.fromString(curSelDate.substring(6, 8) + '/' + curSelDate.substring(4, 6) + '/' + curSelDate.substring(0, 4));
							minDate = parseInt(dtCurSelDate.addDays(addDays * -1).asString2());
							maxDate = parseInt(dtCurSelDate.addDays(addDays * 2).asString2());
						}
						var newNvalues = '';
						var selectQuery = '';
						var selNValues = '';
						// loop through the date range and build the string with the nvalues to select
						// - and build the string with all the querystrings
						for (var i = minDate; i <= maxDate; i++) {
							if (departDates['d' + i] != null && departDates['d' + i] != '') {
								var queryString = departDates['d' + i].split(',')[1];
								var nValue = departDates['d' + i].split(',')[2];
								selNValues += selNValues == '' ? nValue : '+' + nValue;

								var startIndex = queryString.indexOf('N=');
								if (startIndex != -1) {
									var endIndex = queryString.indexOf('&', startIndex);
									if (endIndex == -1) {
										endIndex = queryString.length + 1;
									}
									selectQuery += '||' + queryString.substring(startIndex + 2, endIndex).replace(/\+/g, '||');
								}
							}
						}
						selectQuery += '|';

						// remove the departuredays nvalues, so only the other nvalues are left over
						for (var key in departDates) {
							var nValue2 = departDates[key].split(',')[2];
							if (selectQuery.indexOf('|' + nValue2 + '|') != -1) {
								selectQuery = selectQuery.replace(new RegExp('/|' + nValue2 + '|/', 'g'), '');
							}
						}

						// combine the to selected departuredays nvalues with the other selected nvalues
						var splitOtherNvalues = selectQuery.split('|');
						for (var j = 0; j < splitOtherNvalues.length; j++) {
							if (splitOtherNvalues[j] != '' && ('+' + selNValues + '+').indexOf('+' + splitOtherNvalues[j] + '+') == -1) {
								selNValues += '+' + splitOtherNvalues[j];
							}
						}

						newNvalues = selNValues;
						if (newNvalues == '') {
							newNvalues = '0';
						}
						var newUrl = $.query.REMOVE('No').set('N', newNvalues).set('daterange', daterangeVal);
						location.href = decodeURIComponent(newUrl.toString());
					} else {
						location.href = $.query.empty().set('daterange', daterangeVal);
					}
				}
			}
		},

		getQueryStringWithoutDates: function() {
			var nValues = $.query.get('N').toString().replace(/ /gi, '+');

			if (location.href.indexOf('?') != -1) {
				// undo departure filter
				var queryString = location.href.split('?')[1];
				var arrnValues = nValues.split('+');
				var newNvalues = '';
				for (var key in departDates) {
					var nValue = departDates[key].split(',')[2];
					for (var i = 0; i < arrnValues.length; i++) {
						if (nValue == arrnValues[i]) {
							arrnValues[i] = '';
						}
					}
				}
				for (var j = 0; j < arrnValues.length; j++) {
					if (arrnValues[j] != '') {
						// Do not use '+' as the separator which gets url encoded, use '_' instead.
						newNvalues += newNvalues == '' ? arrnValues[j] : '_' + arrnValues[j];
					}
				}
				if (newNvalues == '') {
					newNvalues = '0';
				}
				var newUrl = $.query.load(queryString).REMOVE('seldate').REMOVE('No').set('N', newNvalues);
				// Replace back above separator by the normal nValue separator +
				return newUrl.toString().replace(/_/gi, '+');
			}
		},

		clearNdp: function(newSearchText) {
			var newUrl = $.query.REMOVE('ndp').REMOVE('Ndp');

			if (typeof (newSearchText) != 'undefined') {
				$.query.SET('searchtext', newSearchText);
			}

			location.href = decodeURIComponent(newUrl.toString() == '' ? '?' : newUrl.toString());
		},

		/**
		* Initializes the logic for the current page
		* to be called on $(document).ready
		*/
		OnReady: function() {
			priv.bindEvents();
			priv.buildCalendar();

			//do favorite logic (bind events, set classes)
			priv.personalItemsLogic();

			priv.initializeFavoritesAndViewed();
		}
	};
} (jQuery);
