﻿/**
 * 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() {

            $('body').bind('mousedown', function(e) {
                if (e.button == 1) {
                    if ($.browser.webkit || $.browser.msie) {
                        e.preventDefault();
                    }
                    else if ($.browser.mozilla) {
                        $('body').trigger('click');
                    }
                }
            });

            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();

        },

        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 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", 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: 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).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(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());


            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";

            $.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)
                ,
                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);
