﻿/**
 * static object that handles page logic
 * @class
 * @constructor
 * @param {jQuery} $ Reference to the jQuery object
 */
var SearchMain = function($) {

	/**
	* @namespace Private methods and variables
	*/
	var priv = {
		freeTextInputElement: "div.search-form input[type=text]",
		freeTextSubmitElement: "div.search-form a.submit",
		searchbarSelectElement: 'form.vacancy-form select',
		showLocationTooltip: true,
		calendarInputElement: 'span.seldate input',
		calendarObj: null,

		/**
		* maximum number of tips to show initially
		* @private
		*/
		maxTips: 10,

		/**
		* holds the name for the current sub-page (tab)
		* @private
		*/
		currentTab: null,

		/**
		* holds the name for the current sub-sub-page (subtab)
		* @private
		*/
		currentSubTab: null,

		/**
		* 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;
		},

		showAirportInfoInLightbox: function(anchor, id) {
			priv.openLightbox(id, {
				container: document.getElementById(id),
				literal: true,
				contentUrl: $(anchor).attr('href'),
				width: '332px'
			});
			return false;
		},

		/**
		* Bind general events for this page
		* @private
		*/
		bindEvents: function() {
			if (location.href.indexOf('personal=') != -1) {
				$('body').addClass('search-personal');
				priv.setCompareChecked();
			}

			priv.bindTextSearch();
			priv.bindHighlightRefinements();
			priv.bindShowOccupancyPopup();
			priv.bindLocationInfoEvents();
			priv.bindMoreInfoEvents();
			if ($('body').attr('class').indexOf('search-offers') > -1) {
				priv.bindQuestionPopups();
			}
			priv.bindAirportInfoEvents();
			priv.bindRemoveLinkEvents();
			priv.bindMiniSkiPopups();
			priv.bindMiniSkiTabs();
		},

		bindAirportInfoEvents: function() {
			// add container for airportinfo popup
			$('body').append("<div id=\"airportInfoPopup\"></div>");

			// Bind methods to show popups for questions in main area
			$('a.airport-info').bind("click", function() {
				return priv.showAirportInfoInLightbox(this, "airportInfoPopup");
			});
		},

		bindRemoveLinkEvents: function() {
			$('#content div.white-box a.remove-all').hover(function() {
				$('#content div.white-box').find('span.remove-link').addClass('remove-hover');
			}, function() {
				$('#content div.white-box').find('span.remove-link').removeClass('remove-hover');
			});

			$('#sidebar div.navigation-refine a.remove').hover(function() {
				$(this).parent().prev('span').addClass('remove-hover');
			}, function() {
				$(this).parent().prev('span').removeClass('remove-hover');
			});

			$('#content div.white-box a.remove').hover(function() {
				$(this).prevAll('span.remove-link').addClass('remove-hover');
			}, function() {
				$(this).prevAll('span.remove-link').removeClass('remove-hover');
			});

			$('#content div.white-box span.ndp a').hover(function() {
				$(this).parent().addClass('remove-hover');
			}, function() {
				$(this).parent().removeClass('remove-hover');
			});
		},

		/**
		* Bind events on the links to MiniSki and MidWeek popups
		* @private
		*/
		bindMiniSkiPopups: function() {
			// add container for miniskipopups
			$('body').append("<div id=\"miniskiPopup\"></div>");

			$('.miniski-block a, .miniski-tab-content a').click(function() {
				var $anchor = $(this);
				var id = 'miniskiPopup';

				var options = {
					container: document.getElementById(id),
					literal: true,
					title: $anchor.text(),
					contentUrl: $anchor.attr('href'),
					width: '643px'
				};
				var lightbox = Lightbox.CreateCached($anchor.attr('href'), options);
				lightbox.Show();
				return false;
			});
		},

		/**
		* Bind events on the tab of the MiniSki, MidWeek, etc blocks
		* @private
		*/
		bindMiniSkiTabs: function() {
			$('.miniski-tab-block ul.main-nav li a').click(function() {
				var contentElementId = $(this).attr('data-content-id');

				//hide all contents
				$(this).parents(".miniski-tab-block").find(".miniski-tab-content").hide();
				//show the content with id indicated by the link clicked
				$("#" + contentElementId).show();

				$(this).parents('ul.main-nav').find("li").removeClass("selected");
				$(this).parents('li').addClass("selected");
			});
		},

		/**
		* 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() {
			if (!priv.showLocationTooltip) {
				return;
			}

			var path = Resource.GetText("path_prefix");
			var ttOptions = {
				trigger: "hover",
				autoClose: true,
				source: "ajax",
				type: "GET",
				loadingText: "",
				loadingImg: "",
				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) {
				if ($.query.get('searchtext').toString() != '') {
					$(priv.freeTextInputElement).val($.query.get('searchtext'));
				}

				$(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 mouseup", function(e) {
					if (e.type == 'focus') {
						$(priv.freeTextSubmitElement).get(0).disabled = false;
						// Compare input text with html decoded sample text
						if (this.value == $('<div/>').html(Resource.GetText('search_free_text')).text()) {
							this.value = '';
						}
						else {
							this.select();
						}
					}
					if (e.type == 'mouseup') {
						return false;
					}
				});
				$(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: 200,
					max: 15,
					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')) {
				var redirectUrl = Resource.GetText('path_prefix') + '/' + Resource.GetText('searchpage') + "?searchtext=" + encodeURIComponent($input.attr("value"));
				location.href = redirectUrl;
			}
		},

		buildCalendar: function() {
			priv.initCalendar();

			$('a.btnSelectDate, a.btnSelectDateAnimate').bind('click', function(e) {
				if (priv.calendarObj) {
					priv.calendarObj.show();
				}
			});
		},

		/**
		* @private
		*/
		initCalendar: function() {
			if (typeof (Calendar) != "undefined" && Calendar) {
				var calendarTime = new Timer();
				var datesObject = priv.getDatesObject();
				// global variables like reloadWithAjax, showImageLink coming from user controls should be checked for existence before using
				priv.calendarObj = new Calendar({
					inputElement: priv.calendarInputElement,
					showImageLink: typeof (showImageLink) != "undefined" && showImageLink == 'true',
					updateInputOnSelect: false,
					hideDatePickerOnSelect: false,
					datesObject: datesObject,
					numberOfMonths: typeof (departureMonthSelected) != "undefined" && departureMonthSelected == 'True' ? 1 : 3,
					hideIfNoPrevNext: typeof (departureMonthSelected) != "undefined" && departureMonthSelected == 'True' ? true : false
				});

				var curSelDate = $('#hidSelDate').length ? $('#hidSelDate').val() : $.query.get('seldate').toString();
				var daterange = $.query.get('daterange') != '' ? $.query.get('daterange') : $('select.daterange').val();
				var addDays = priv.getAddDays(daterange);
				priv.calendarObj.build(curSelDate, addDays);

				Log.Info("Main: Calendar Javascript init time was: " + (calendarTime.Stop()) + "ms ", -1);
			}
		},

		getDatesObject: function() {
			if (typeof (firstDate) == "undefined" || typeof (lastDate) == "undefined" || typeof (departDates) == "undefined") {
				return null;
			}

			return {
				firstDate: firstDate,
				lastDate: lastDate,
				departDates: departDates
			};
		},

		getAddDays: function(daterange) {
			var addDays = 0;

			if (daterange == '2') {
				addDays = 3;
			} else if (daterange == '3') {
				addDays = 7;
			} else {
			}

			return addDays;
		},

		bindSearchbarEvents: function() {
			priv.buildCalendar();
			$(priv.searchbarSelectElement + ',form.vacancy-form input:radio').bind('change', function() {
				priv.searchbarChange();
			});
		},

		searchbarLock: false,
		setSearchbarLock: function() {
			priv.searchbarLock = true;
			//do some loading animation here
			$(priv.searchbarSelectElement).attr("disabled", "disabled");
			var overlay = document.createElement("DIV");
			var loader = document.createElement("DIV");
			var fullHeight = $('#searchbar').height();
			var fullWidth = $('#searchbar').width()
			$(overlay).css({ "z-index": 4, "opacity": 0.75, "position": "absolute", "top": 0, "left": 0, "background": $('#searchbar').css("background-color") }).height(fullHeight).width(fullWidth);
			$(loader).css({ "position": "absolute", "top": 0, "left": 0, "z-index": 5, "background": "transparent url(" + Resource.GetText('path_prefix') + "/images/ajax-loader-02.gif) no-repeat center" }).height(fullHeight).width(fullWidth);
			$("#searchbar fieldset").css("position", "relative").append(overlay).append(loader);
		},

		searchbarChange: function() {
			//do nothing if we are locked
			if (priv.searchbarLock) {
				return;
			}
			priv.setSearchbarLock();

			var selectedNValues = [];

			var occupancy = $('#reisgezelschap1').val();
			if (occupancy != null && occupancy != Occupancy.getOccupancy()) Occupancy.saveTotalTravelers(occupancy);

			selectedNValues.push($('#airport').val());
			selectedNValues.push($('#destination').val());
			selectedNValues.push($('#reisduur').val());
			selectedNValues.push($('#accommodatiesoort').val());
			selectedNValues.push($('#verzorging').val());
			selectedNValues.push($('#vervoer').val());
			selectedNValues.push($('#vertrekmaand').val());
			selectedNValues.push($('#pistedistance').val());
			selectedNValues.push($('#packages').val());
			selectedNValues.push($("input:radio:checked[@name='packagegroup']").val());


			var filteredNValues = [];
			for (var i = 0; i < selectedNValues.length; i++) {
				if (selectedNValues[i] && selectedNValues[i] != -1) {
					filteredNValues.push(selectedNValues[i]);
				}
			}

			var loadcontrol = "~/controls/common/searchbar.ascx";
			var currentpageParam = ""
			if (document.location.href.indexOf("quickfinder.aspx") != -1) {
				currentpageParam = "&currentpage=quickfinder";
			}
			$.ajax({
				// hack (Alexander): make a sync AJAX request.
				// Under some conditions an unknown handler executes right after this $.ajax call, 
				// but before result is received and parsed, and redirects to the wrong page.
				// The bug is that in FF on test server when on search page you filter by date with datePicker,
				// after filtering by e.g. destination, search result is incorrect
				// and query string in browser is ?unknown instead of ?N=0+... which probably corresponds to the line below:
				// location.href = currentLocation + '?' + $("#queryString").val();
				// async: false helps, because in this case that evil handler does not get an opportunity to execute.
				// As soon as race condition is fixed, async: false should be removed.
				async: true,
				url: Resource.GetText('path_prefix') + "/js/ajax/getcontrol.aspx",
				data: "N=" + filteredNValues.join('+') //todo
                        + "&loadControl=" + encodeURI(loadcontrol)
                        + currentpageParam
                ,
				cache: false,
				success: function(result) {
					$('#searchbar').replaceWith(result);
					priv.bindSearchbarEvents();

					//unlock
					priv.searchbarLock = false;
				}
			});
		},

		/**
		* Void, fills the property currentTab with the correct value
		* @private
		*/
		setCurrentTab: function() {
			priv.currentTab = $.query.get('view').toLowerCase();
			if (priv.currentTab.length < 1) {
				priv.currentTab = $('body').attr('class');
			}
			Log.Debug("SearchMain: currentTab is '" + priv.currentTab + "'");
		},

		/**
		* Void, fills the property currentTab with the correct value
		* @private
		*/
		setCurrentSubTab: function() {
			priv.currentSubTab = $.query.get('sub').toLowerCase();
			if (priv.currentSubTab.length < 1) {
				priv.currentSubTab = $('body').attr('class');
			}
			Log.Debug("AccoMain: currentSubTab is '" + priv.currentSubTab + "'");
		},

		/** 
		* TODO: Duplicate function of location.js. This method should be moved in a generic class that is accessible.
		*/
		resizeMapBox: function() {
			var maxHeight = $('#static-map-container').height() - 10;
			var resourcetxt = priv.currentTab == "countryinfo" ? Resource.GetText("more_locations_show_country") : Resource.GetText("more_locations_show_region");
			if (maxHeight > 0) {
				if ($('.map-box').height() > maxHeight) {
					$('.map-box .locations').append('<li><a class="more-locations-show">' + resourcetxt + '&nbsp;<img src="' + Resource.GetText('path_prefix') + '/images/arrow-02.gif" heigth="6" width="5" alt="" style="display:inline" /></a></li>');
					$('.map-box .more-locations').append($('<ul></ul>'));
				}

				while ($('.map-box').height() > maxHeight) {
					var length = $('.map-box .locations li').length;
					var removedElement = $('.map-box .locations li:eq(' + (length - 2) + ')').remove();
					$('.map-box .more-locations ul').prepend(removedElement);
				}

				$('.more-locations-show').bind('click', function(e) {
					$('.more-locations').toggle();
				});

				$('.more-locations-close').bind('click', function(e) {
					$('.more-locations').hide();
				});
			}
		}
	};

	/** @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') {
				if (newSearchText == '') {
					$.query.REMOVE('searchtext');
				} else {
					$.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.bindSearchbarEvents();

			priv.setCurrentTab();
			priv.setCurrentSubTab();

			if (priv.currentTab == 'countryinfo' || priv.currentTab == 'regioninfo' || priv.currentTab == 'cityinfo') {
				priv.resizeMapBox();
			}

			if (priv.currentSubTab == "weather") {
				if (typeof (WeatherMain) != "undefined" && WeatherMain) {
					WeatherMain.AddEvenOddClasses();
				}
			} else if (priv.currentSubTab == "tips") {
				Main.hideItems(priv.maxTips, "tips", "#tip-count");
			}
		}
	};
} (jQuery);
