﻿/**
 * 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: "#homesearch",
        freeTextSubmitElement: "#homesearchbutton",
        searchbarSelectElement: 'form.select-form select',
        showLocationTooltip: false,
        selectedDateNValue: "",
        selectedDateParam: "",

        /**
        * 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.bindLocationInfoEvents();
            priv.bindMoreInfoEvents();
            if ($('body').attr('class').indexOf('search-offers') > -1) {
                priv.bindQuestionPopups();
            }
        },

        /**
        * 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;
            });
        },

        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(" + 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 = $('#reisgezelschap').val();
            if (occupancy != null && occupancy != Occupancy.getOccupancy()) Occupancy.saveTotalTravelers(occupancy);

            selectedNValues.push($('#destination').val());
            selectedNValues.push($('#lowestprice').val());
            selectedNValues.push($('#pistedistance').val());
            selectedNValues.push(priv.selectedDateNValue);

            var filteredNValues = [];
            for (var i = 0; i < selectedNValues.length; i++) {
                if (selectedNValues[i] && selectedNValues[i] != -1) {
                    filteredNValues.push(selectedNValues[i]);
                }
            }

            var loadcontrol = "~/controls/home/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 + priv.selectedDateParam
                ,
                cache: false,
                success: function(result) {
                    $('#searchbar').replaceWith(result);
                    priv.bindSearchbarEvents();

                    //unlock
                    priv.searchbarLock = false;
                }
            });
        },

        inputSubmit: function() {
            if ($('#homesearch').val() != null && $('#homesearch').val() != "") {
                $('#homesearch').val($('#homesearch').val().replace('bijv: ', ''));
                $('#form-search').get(0).submit();
            }
        },

        /**
        * 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: 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: 175,
                    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')) {
                if (location.href.indexOf('lastminutes.aspx') > -1)
                    document.location.href = Resource.GetText("path_prefix") + "/lastminutes.aspx?searchtext=" + encodeURI($input.attr("value"));
                else

                    document.location.href = Resource.GetText("path_prefix") + "/search.aspx?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 == '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();
            var ndp = $.query.get('Ndp').toString();
            if (ndp != '') {
                var minDateSet = false;
                for (key in departDates) {
                    if (!minDateSet) {
                        curMinDate = key.replace('d', '');
                        minDateSet = true;
                    }
                    curMaxDate = key.replace('d', '');
                }
            }
            else 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('1');
                }

                // 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];
                    }
                }

                if ($('#start-date').hasClass('date-pick')) {
                    priv.selectedDateNValue = selNValues;
                    priv.selectedDateParam = '&seldate=' + selectedDate.asString2();
                    //$('#date-popup').hide();
                    reloadDates = 'True'
                    priv.searchbarChange();
                }
                else {
                    // 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, span.departure-selector').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();
            }
        }
    };

    /** @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] != '') {
                        newNvalues += newNvalues == '' ? arrnValues[j] : '+' + arrnValues[j];
                    }
                }
                if (newNvalues == '') {
                    newNvalues = '0';
                }
                var newUrl = $.query.load(queryString).REMOVE('seldate').REMOVE('No').set('N', newNvalues);
                return newUrl.toString();
            }
        },

        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.bindSearchbarEvents();
        }
    };
} (jQuery);
