/*global IAD, jQuery, alert
*/

// Initialize IAD and IAD.travel namespaces
var IAD = IAD || {};
IAD.travel = IAD.travel || {};



/* extend jQuery with common utility functions */

jQuery.fn.show_only_if = function (test) {
    this.each(function () {
        if (test.apply(this)) {
            jQuery(this).show();
        } else {
            jQuery(this).hide();
        }
    });
    return this; // don't break the chain
};

jQuery.fn.count_number_of = function (test) {
    var number = 0;
    this.each(function () {
        if (test.apply(this)) {
            number = number + 1;
        }
    });
    return number;
};

jQuery.fn.has_any = function (test) {
    var any = false;
    this.each(function () {
        any = any || test.apply(this);
    });
    return any;
};

jQuery.fn.exists = function () {
    return this.length > 0;
};

/**
 * Focus the input field that naturally comes after the selected field.
 * Copied from http://jqueryminute.com/set-focus-to-the-next-input-field-with-jquery
 */
jQuery.fn.focus_next_input_field = function() {
    return this.each(function() {
        var fields = $(this).parents('form:eq(0),body').find(':input').not('[type=hidden]');
        var index = fields.index( this );
        if ( index > -1 && ( index + 1 ) < fields.length ) {
            fields.eq( index + 1 ).focus();
        }
        return false;
    });
};

/* FLIGHT SEARCH - START */

/* Callback function for calendar script */
function departureCalendarOnSelect(calendar, date) {
    if (calendar.dateClicked) {
        var inputField = document.forms.flightticketsearch.formattedDepartureDate;
        // update hidden field
        inputField.value = date;

        // update dropdowns
        document.forms.flightticketsearch.departureDateD.value = inputField.value.substring(8, 10);
        document.forms.flightticketsearch.departureDateYM.value = inputField.value.substring(0, 7);
        document.forms.flightticketsearch.departureDateD.onchange();

        // call event handler
        calendar.callCloseHandler();
    }
}

/* Callback function for calendar script */
function returnCalendarOnSelect(calendar, date) {
    if (calendar.dateClicked) {
        var inputField = document.forms.flightticketsearch.formattedReturnDate;

        // update hidden field
        inputField.value = date;

        // update dropdowns
        document.forms.flightticketsearch.returnDateD.value = inputField.value.substring(8, 10);
        document.forms.flightticketsearch.returnDateYM.value = inputField.value.substring(0, 7);
        updateDateWithWeekday('departureDateYM', 'departureDateD', 'formattedDepartureDate', 'returnDateYM', 'returnDateD', 'formattedReturnDate', '', 'departureDateW', 'returnDateW');
        updateDateWithWeekday('returnDateYM', 'returnDateD', 'formattedReturnDate', '', '', '', '', 'returnDateW', 'departureDateW');
        calendar.callCloseHandler();
    }
}

function toggleOneWay() {
    var e;

    if (document.forms.flightticketsearch.oneWay.checked) {
        e = document.getElementById('returnDate');
        if (e != null) {
            e.style.display = "none";
        }

        e = document.getElementById('returnDateLabel');
        if (e != null) {
            e.style.display = "none";
        }
    } else {
        e = document.getElementById('returnDate');
        if (e != null) {
            e.style.display = "block";
        }

        e = document.getElementById('returnDateLabel');
        if (e != null) {
            e.style.display = "inline";
        }
    }
}


function loadCookie(weekdays, dateFormat, formref) {
    //Remove expired cookie before loading a new one
    var expCookie = new Cookie(document, "reise", 2400, "/");
    expCookie.remove();

    var cookie = new Cookie(document, "travel", 2400, "/");
    var f = document.forms[formref]; //.flightticketsearch;
    cookie.load();

    //console.log(cookie.dt1);
    if (cookie.dt1) {
        var flights = document.forms[formref];
        var d;
        if (!getParameter("depDate")) {
            d = Date.parseString(cookie.dt1, dateFormat);
        }
        else {
            d = Date.parseString(getParameter("depDate"), dateFormat);
        }

        var today = new Date();

        if (d > today) {
            if(formref=='carsearch'){
                // Do not use pick up place from cookie when "areaId" is supplied:
                if (! getParameter("areaId")) {
                    if (cookie.dN) {
                        f.locOriginName.value = cookie.dN;
                        f.locOriginNameHidden.value = cookie.dN;
                    }
                    if (cookie.dC) {
                        f.locOriginCodes.value = cookie.dC;
                    }
                }

                if (cookie.oN) {
                    f.locDestinationName.value = cookie.dN;
                    f.locDestinationNameHidden.value = cookie.dN;
                }
                if (cookie.oC) {
                    f.locDestinationCodes.value = cookie.dC;
                }
            }
            else{
                // Do not use origin from cookie when "areaId" is supplied:
                if (! getParameter("originAreaId")) {
                    if (cookie.oN) {
                        document.forms[formref].locOriginName.value = cookie.oN;
                        document.forms[formref].locOriginNameHidden.value = cookie.oN;
                    }
                    if (cookie.oC) {
                        document.forms[formref].locOriginCodes.value = cookie.oC;
                    }
                }
                // Do not use destination from cookie when already set:
                if (! document.forms[formref].locDestinationName.value) {
                    if (cookie.dN) {
                        document.forms[formref].locDestinationName.value = cookie.dN;
                        document.forms[formref].locDestinationNameHidden.value = cookie.dN;
                    }
                    if (cookie.dC) {
                        document.forms[formref].locDestinationCodes.value = cookie.dC;
                    }
                }
            }
            flights.depDate.value = d.format(dateFormat);

            var innerh = document.getElementById("departure-weekday");
            if (innerh) {
                innerh.innerHTML = weekdays[d.getDay()];
            }

            if (cookie.dt2) {
                var d2;
                if (!getParameter("retDate")) {
                    d2 = Date.parseString(cookie.dt2, dateFormat);    
                }
                else {
                    d2 = Date.parseString(getParameter("retDate"), dateFormat);
                }

                flights.retDate.value = d2.format(dateFormat);

                var innerA = document.getElementById("return-weekday") ;
                if (innerA) {
                    innerA.innerHTML = weekdays[d2.getDay()];

            }
            }
            if (cookie.nAd && f.noOfAdults) {
                document.forms[formref].noOfAdults.value = cookie.nAd;
            }
            if (cookie.nCh && f.noOfChildren) {
                f.noOfChildren.value = cookie.nCh;
                if (cookie.aCh) {
                    var ageArray = cookie.aCh.split(',');
                    if (ageArray[0]) f.ageOfChild_0.value = ageArray[0];
                    if (ageArray[1]) f.ageOfChild_1.value = ageArray[1];
                    if (ageArray[2]) f.ageOfChild_2.value = ageArray[2];
                    if (ageArray[3]) f.ageOfChild_3.value = ageArray[3];
                    if (ageArray[4]) f.ageOfChild_4.value = ageArray[4];
                    if (ageArray[5]) f.ageOfChild_5.value = ageArray[5];
                    if (ageArray[6]) f.ageOfChild_6.value = ageArray[6];
                    if (ageArray[7]) f.ageOfChild_7.value = ageArray[7];
                    if (ageArray[8]) f.ageOfChild_8.value = ageArray[8];
                }
            }
        }
    }
}


/* FLIGHT SEARCH - END */


function disableAjaxIfOpera(form) {
    if (window.opera) {
        if (form.locOriginName.onkeypress) {
            form.locOriginName.onkeypress = null;
        }
        if (form.locOriginName.onkeydown) {
            form.locOriginName.onkeydown = null;
        }
        if (form.locOriginName.onkeyup) {
            form.locOriginName.onkeyup = null;
        }
        if (form.locDestinationName.onkeypress) {
            form.locDestinationName.onkeypress = null;
        }
        if (form.locDestinationName.onkeydown) {
            form.locDestinationName.onkeydown = null;
        }
        if (form.locDestinationName.onkeyup) {
            form.locDestinationName.onkeyup = null;
        }

        form.locOriginCodes.value = "";
        form.locDestinationCodes.value = "";
    }
}

//
// get parameter from URL
// parameter - the name of the parameter
function getParameter(parameter) {
    if (! window.location.search) {
        // no search string, no parameters
        return null;
    }

    var list = window.location.search.substring(1).split("&");
    if (list) {
        for (var i=0; i<list.length; i++) {
            var pair = list[i].split("=");

            if (parameter == pair[0]) {
               return pair[1];
            }
        }
    }

    return null;
}

//
// parse a date
// d - a String with a date on the format yyyy-MM-dd
function parseDate(d, format) {
    /*var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

    var year;
    var month;
    var day;
    var hour;
    var min;

    if (d.length >= 10) {
        year = d.substring(0,4);
        month = d.substring(5,7) - 1;
        day = d.substring(8,10);

        // date also includes timestamp
        if (d.length == 16) {
            hour = d.substring(11,13);
            min = d.substring(14,16);
        }
    } else {
        // unknown format
        return null;
    }

    if (day > days[month]) {
        // check for leap years, - Any year divisible by 4, except those divisible by 100 (but NOT 400)
        if (month == 1 && day == 29 && ((year%4==0) && ((year%100!=0) || (year%400==0)))) {
            // leap day
            return new Date(year, month, day);
        }

        // illegal day
        return null;
    }

    if (hour && min) {
        return new Date(year, month, day, hour, min);
    } else {
        return new Date(year, month, day);
    } */


    /*
    * Using extra date functions provided by Date.js
    * These functions are used to parse, format, and manipulate Date objects.
    * See documentation and examples at http://www.JavascriptToolbox.com/lib/date/
    */
    return Date.parseString(d, format);
}

//
// validate dates (d1, d2)
// elementId - div tag as placeholder for error message.
// d1 - a Date object or a String with a date on the format yyyy-MM-dd
// d2 - a Date object or a String with a date on the format yyyy-MM-dd
// dateText - two element array with date "names" for error messages.
// equalInvalid - true, if equal dates is invalid
function validateDates(elementId, d1, d2, dateFormat, dateText, equalInvalid, errMsgVal) {
    var date1 = d1;
    var date2 = d2;
    var now = new Date();
    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());

    if (! (date1 instanceof Date)){
        date1 = parseDate(d1, dateFormat);
        if (date1 == null) {
            showResponseMessage(elementId, dateText[0] + " " + errMsgVal[0], 0);
            return false;
        }
    }

    if (! (date2 instanceof Date)) {
        date2 = parseDate(d2, dateFormat);
        if (date2 == null) {
            showResponseMessage(elementId, dateText[1] + " " + errMsgVal[0], 0);
            return false;
        }
    }

    if (equalInvalid && (date1.getTime() == date2.getTime())) {
        showResponseMessage(elementId, dateText[0] + " " + errMsgVal[1] + " " + dateText[1].toLowerCase() + ".", 0);
        return false;
    }

    if (date1 > date2) {
        showResponseMessage(elementId, dateText[1] + " " + errMsgVal[2] + " " + dateText[0].toLowerCase() + ".", 0);
        return false;
    }

    if (date1 < today) {
        showResponseMessage(elementId, dateText[0] + " " + errMsgVal[3], 0);
        return false;
    }

    //
    return true;
}

//
// show a response message in HTML
// elementId - placeholder element tag (if null, use alert()).
// message - the message
// severity - the severity
function showResponseMessage(elementId, message, severity) {
   if (message != null) {
     var e = document.getElementById(elementId);
     if (e != null) {
       e.innerHTML = '<div class="responseseverity0"><div class="responsemessage"><table cellspacing="0"><tr><td class="signal"></td><td class="text">' + message + '</td></tr></table></div></div>';
     } else {
       alert(message);
     }
   }
}


//
// update date field for synchronizing dropdown and calendar.
// can be used to also update another set of dropdowns.
// dateYM - year-month dropdown
// dateD - date dropdown
// date - placeholder date field
// linkedDateYM - year-month dropdown
// linkedDateD - date dropdown
// linkedDate - placeholder date field
// diff - date offset between date and linked date.
function updateDate(dateYM, dateD, date, linkedDateYM, linkedDateD, linkedDate, diff) {

    var dropdownYM = document.getElementById(dateYM);
    if (dropdownYM == null) { return; }

    var dropdownD = document.getElementById(dateD);
    if (dropdownD == null) { return; }

    var dateField = document.getElementById(date);
    if (dateField == null) { return; }

    var day = dropdownD.value;
    dateField.value = dropdownYM.value + "-" + day;

    if (arguments.length >= 6) {
        // update linked date fields
        var linkedDropdownYM = document.getElementById(linkedDateYM);
        if (linkedDropdownYM == null) { return; }

        var linkedDropdownD = document.getElementById(linkedDateD);
        if (linkedDropdownD == null) { return; }

        var linkedDateField = document.getElementById(linkedDate);
        if (linkedDateField == null) { return; }

        var d1 = new Date(dateField.value.substring(0,4), dateField.value.substring(5,7)-1, dateField.value.substring(8, 10));
        var d2 = new Date(linkedDateField.value.substring(0,4), linkedDateField.value.substring(5,7)-1, linkedDateField.value.substring(8, 10));


        if (d1 >= d2) {
            if (diff == null) {
                diff = 0;
            }

            d2.setTime(d1.getTime() + diff * 24 * 3600 * 1000);

            var d = d2.getDate();
            if (d<10) {
                d = "0" + d;
            }
            var m = d2.getMonth() + 1;
            if (m<10) {
                m = "0" + m;
            }
            var y = d2.getFullYear();

            linkedDropdownYM.value = y + "-" + m;
            linkedDropdownD.value = d;
            linkedDateField.value =  y + "-" + m + "-" + d;
        }
    }
}

//
// update date field for synchronizing dropdown.
// can be used to also update another set of dropdowns.
// dateYM - year-month dropdown
// dateD - date dropdown
// date - placeholder date field
// linkedDateYM - year-month dropdown
// linkedDateD - date dropdown
// linkedDate - placeholder date field
// diff - date offset between date and linked date.
// weekdayField - id of field to be updated with weekday
// linkedWeekdayField - id of field to be updated with weekday

function updateDateWithWeekday(dateYM, dateD, date, linkedDateYM, linkedDateD, linkedDate, diff, weekdayField, linkedWeekdayField) {
    var dropdownYM = document.getElementById(dateYM);
    if (dropdownYM == null) { return; }

    var dropdownD = document.getElementById(dateD);
    if (dropdownD == null) { return; }

    var dateField = document.getElementById(date);
    if (dateField == null) { return; }


    var day = dropdownD.value;
    dateField.value = dropdownYM.value + "-" + day;

    var d3 = new Date(dateField.value.substring(0,4), dateField.value.substring(5,7)-1, dateField.value.substring(8, 10));

    var weekdayValue = document.getElementById(weekdayField) ;

    if (weekdayValue) {
        var weekdays;
        if (weekdayField) {
            weekdays = jQuery(".weekday").map(function (index, weekday) { return jQuery(weekday).html(); });
        }
        weekdayValue.innerHTML =  weekdays[d3.getDay()];
    }

    if (arguments.length >= 6) {

        // update linked date fields
        var linkedDropdownYM = document.getElementById(linkedDateYM);
        if (linkedDropdownYM == null) { return; }

        var linkedDropdownD = document.getElementById(linkedDateD);
        if (linkedDropdownD == null) { return; }

        var linkedDateField = document.getElementById(linkedDate);
        if (linkedDateField == null) { return; }

        var d1 = new Date(dateField.value.substring(0,4), dateField.value.substring(5,7)-1, dateField.value.substring(8, 10));
        var d2 = new Date(linkedDateField.value.substring(0,4), linkedDateField.value.substring(5,7)-1, linkedDateField.value.substring(8, 10));


        if (d1 >= d2) {
            if (diff == null) {
                diff = 0;
            }

            d2.setTime(d1.getTime() + diff * 24 * 3600 * 1000);

            var d = d2.getDate();
            if (d<10) {
                d = "0" + d;
            }
            var m = d2.getMonth() + 1;
            if (m<10) {
                m = "0" + m;
            }
            var y = d2.getFullYear();

            linkedDropdownYM.value = y + "-" + m;
            linkedDropdownD.value = d;
            linkedDateField.value =  y + "-" + m + "-" + d;

            weekdayValue = document.getElementById(linkedWeekdayField) ;
            if (weekdayValue) {
                weekdayValue.innerHTML =  weekdays[d2.getDay()];
            }
        }
    }
}

//
// disable dates in calendar (see calendar.js)
// date - the date
function disableDate(date) {
    // return true to disable date
    var now = new Date();
    var today = new Date(now.getFullYear(), now.getMonth(), now.getDate());

    // disable before today.
    if (date.getTime() < today.getTime()) {
        return true;
    }

    // only enable 11 months ahead
    var maxMonth = today.getMonth() + 1 + 11;     // adjust for 0-based index
    var maxYear = today.getFullYear()

    var rest = maxMonth % 12;
    if (rest != 0) {
        maxYear += 1;
        maxMonth = rest - 1;            // adjust for 0-based index
    } else {
        maxMonth = maxMonth + 11 - 1;   // adjust for 0-base index
    }

    if (date.getFullYear() < maxYear) {
        return false;
    }

    if ((date.getFullYear() == maxYear) && (date.getMonth() <= maxMonth)) {
        return false;
    }

    return true;
}


//
// update hidden field with text from dropdown
// formId - the form id
// dropdownId - the dropdown id
// fieldId - the field id
function updateField(formId, dropdownId, fieldId) {
    var f = document.getElementById(formId);

    if (f != null && f[dropdownId] && f[fieldId]) {
        var dropdown = f[dropdownId];
        var field = f[fieldId];
        field.value = dropdown[dropdown.selectedIndex].text;
    }
}

IAD.travel.hotel_admin = function ($) {
    var urls, text; // injected in initialize

    function sethotelpassive(event){
        var id = $(this).parents("tr:first").attr("id");
        var passiveUrl = urls.set_passive + 'json=true&hotelId=' + id;

        $.getJSON(passiveUrl,function(data){
           if(data.status=="0"){
               $('#deleted'+id).remove();
                $('#'+id).children().show();
                event.preventDefault();
                return false;
           }
           else if(data.status=="-1"){
               alert(text.msg_err_passive);
           }
        });
    }

    function sethotelactive(event) {
        var name = $(this).parents("tr:first").find("td.hotelname").html();
        var id = $(this).parents("tr:first").find("td.hotelid").html();
        var url = urls.set_active + 'json=true&hotelId=' + id;
        $("#updatemessage").fadeOut();
        $(this).parents("tr:first").find("td.activate").addClass("loading");
        $.getJSON(url,function(data){
            $("#"+id).parents().find("td.activate").removeClass("loading");
            if(data.status=="0"){
                $('#'+id).children().hide();
                $('#'+id).append("<td id=\"deleted" + id + "\" colspan=\"7\">" + name + " (" + id + ") " + text.msg_active + "<a id=\"regret" + id + "\" href=\"#\">" + " " + text.regret + "</a></td>")
                    .find("a#regret"+id).click(sethotelpassive);
            }
            else if(data.status=="-1"){
                alert(text.msg_err_active);
            }
        });
        event.preventDefault();
        return false;
    }

    function hotelupdate(event) {
        var name = $(this).parents("tr:first").find("td.hotelname").html();
        var id = $(this).parents("tr:first").find("td.hotelid").html();
        var url = urls.update + 'json=true&hotelId=' + id;
        $("#updatemessage").fadeOut();
        $(this).parents("tr:first").find("td.update").addClass("loading");
        $.getJSON(url,function(data){
            $("#"+id).parents("tr:first").find("td.update").removeClass("loading");
            if(data.status=="0"){
                $('#'+id).children().hide();
                $('#'+id).append("<td id=\"updated" + id + "\" colspan=\"7\">" + name + " (" + id + ") " + text.msg_updated + " <a id=\"finishedupdate" + id + "\" href=\"#\">" + " " + text.ok + "</a></td>")
                    .find("a#finishedupdate"+id).click(finishedupdate);
            }
            else if(data.status=="-1"){
                alert(text.msg_err_update);
            }
        });
        event.preventDefault();
        return false;
    }

    function finishedupdate(event){
        var id = $(this).parents("tr:first").attr("id");
        $('#updated'+id).remove();
        $('#'+id).children().show();
        event.preventDefault();
        return false;}

    return {
        initialize: function (data) {
            urls = data.urls;
            text = data.text;

            $('#passive-hotels table').tablesorter({
                widthFixed: false,
                widgets: ['zebra'],
                headers: {
                0: {sorter:"text"},
                1: {sorter:"text"},
                2: {sorter:"text"},
                3: {sorter:"date"},
                4: {sorter:"text"},
                5: {sorter:false},
                6: {sorter:false}},
                sortList: [[3,1]]
             });

            $("a.activate_link").click(sethotelactive);
            $("a.update_link").click(hotelupdate);
        }
    };
}(jQuery);

(function ($) {

    //  Form validation with error messages and highlighting of fields.
    //
    //  Rule-objects are in this form: {
    //      is_valid: function () { ... },
    //      elements_to_highlight: function () { ... },
    //      error_message: "..."
    //  }
    //
    //  See air_search_form.js for example usage.
    //
    IAD.travel.form_validator = function (rules) {
        var error_class = "error-highlight-border", on_success;

        function invalid_rule() {
            return ! this.is_valid();
        }

        function form_is_valid() {
            return ! rules.has_any(invalid_rule);
        }

        function validation_errors() {
            return rules.filter(invalid_rule);
        }

        function build_error_messages_html() {
            return $(validation_errors()).map(function () {
                return "<li>" + this.error_message + "</li>";
            }).get().join("\n");
        }

        function build_error_messages_alert() {
            return $(validation_errors()).map(function () {
                return this.error_message;
            }).get().join("\n");
        }

        function display_error_messages() {
            if ($('#errorMsg-placeholder ul').length > 0) {
                $('#errorMsg-placeholder').show().addClass('errorMsg').find('ul').html(build_error_messages_html());
            } else {
                alert(build_error_messages_alert());
            }
        }

        function highlight_if_invalid() {
            if (! this.is_valid()) {
                this.elements_to_highlight().addClass(error_class);
            }
        }

        function remove_current_highlights() {
            $("." + error_class).removeClass(error_class);
        }

        function highlight_invalid_fields() {
            remove_current_highlights();
            rules.each(highlight_if_invalid);
        }

        function display_validation_errors() {
            highlight_invalid_fields();
            display_error_messages();
        }

        function remove_validation_errors() {
            remove_current_highlights();
            $('#errorMsg-placeholder').hide();
        }

        function validate_form(event) {
            if (form_is_valid()) {
                remove_validation_errors();
                if (on_success) {
                    on_success();
                }
                return true;
            } else {
                display_validation_errors();
                event.preventDefault();
                return false;
            }
        }

        return {
            initialize: function (form) {
                $(form).submit(validate_form);
            },
            on_success_do: function (callback) {
                on_success = callback;
            }
        };
    };

    // adds datepickers to all inputs on page with class datepicker.
    //
    IAD.travel.datepickers = IAD.travel.datepickers || function () {
        var info, on_select_callbacks = [];

        function today() {
            return Date.parseString(new Date().format("dd.MM.yyyy"), "dd.MM.yyyy"); // strips hours, minutes and seconds from todays date
        }

        function next_year() {
            return today().add("y", 1);
        }

        function from_date_fields() {
            return $('input.datepicker_field.from_date');
        }

        function to_date_fields() {
            return $('input.datepicker_field.to_date');
        }

        function master_from_date_field() {
            return from_date_fields().filter(":first");
        }

        function master_to_date_field() {
            return to_date_fields().filter(":first");
        }

        function selected_from_date() {
            return Date.parseString(master_from_date_field().val(), info.date_format);
        }

        function selected_to_date() {
            return Date.parseString(master_to_date_field().val(), info.date_format);
        }

        function from_date_is_set() {
            return master_from_date_field().val() !== "";
        }

        function to_date_is_set() {
            return master_to_date_field().val() !== "";
        }

        function set_from_date(date) {
            from_date_fields().attr("value", date.format(info.date_format));
        }

        function set_to_date(date) {
            to_date_fields().attr("value", date.format(info.date_format));
        }

        function both_dates_are_set() {
            return from_date_is_set() && to_date_is_set();
        }

        function dates_are_in_chronological_order() {
            return both_dates_are_set() && selected_to_date().isAfter(selected_from_date());
        }

        function dates_are_in_the_future() {
            return both_dates_are_set() && selected_to_date() >= today() && selected_from_date() >= today();
        }
        
        function date_range_for_from_date() {
            return {
                minDate: today(),
                maxDate: next_year()
            };
        }

        function date_range_for_to_date() {
            return {
                minDate: selected_from_date() || today(),
                maxDate: next_year()
            };
        }

        function enforce_selectable_date_ranges(input) {
            if ($(input).is(".from_date")) {
                return date_range_for_from_date();
            }
            if ($(input).is(".to_date")) {
                return date_range_for_to_date();
            }
            return {};
        }

        function day_after_from_date() {
            return selected_from_date() && selected_from_date().add("d", 1);
        }

        function day_before_to_date() {
            return selected_to_date() && selected_to_date().add("d", -1);
        }

        function autofill_the_other_date_box() {
            if (from_date_is_set() && ! to_date_is_set()) {
                set_to_date(day_after_from_date());
            }
            if (to_date_is_set() && ! from_date_is_set()) {
                set_from_date(day_before_to_date());
            }
        }

        function enforce_date_logic() {
            if (! dates_are_in_the_future()) {
                set_from_date(today());
            }
            if (! dates_are_in_chronological_order()) {
                set_to_date(day_after_from_date());
            }
        }

        function update_mirroring_fields(master) {
            var new_value = master.val();
            if (master.is(".from_date")) {
                from_date_fields().val(new_value);
            } else if (master.is(".to_date")) {
                to_date_fields().val(new_value);
            }
        }

		function dayname(date) {
			return info.datepicker_settings.dayNames[date.getDay()];
		}

		function update_day_names() {
            if (from_date_is_set()) {
                $(".departure-weekday").html(dayname(selected_from_date()));
            }
            if (to_date_is_set()) {
                $(".return-weekday").html(dayname(selected_to_date()));
            }
		}

        function handle_selected_date() {
            var changed_field = $(this);
            update_mirroring_fields(changed_field);
            autofill_the_other_date_box();
            if (changed_field.is(".from_date")) {
                enforce_date_logic();
            }
            update_day_names();
            $(on_select_callbacks).each(function () {
                this.apply(changed_field);
            });
        }

        function is_on_search_box_page() {
            return $("#search-tabs").length > 0;
        }

        function number_of_months() {
            return is_on_search_box_page() ? 1 : 2;
        }

        function datepicker_settings() {
            var settings = info.datepicker_settings;
            settings.firstDay = 1;
            settings.changeFirstDay = false;
            settings.changeMonth = false;
            settings.changeYear = false;
            settings.closeAtTop = false;
            settings.showOtherMonths = false;
            settings.showOn = 'both';
            settings.mandatory = true;
            settings.buttonImageOnly = true;
            settings.speed = 1;
            settings.autoPopUp = 'both';
            settings.onSelect = handle_selected_date;
            settings.beforeShow = enforce_selectable_date_ranges;
            settings.numberOfMonths = number_of_months();
            return settings;
        }

        return {
            initialize: function (_info) {
                info = _info;
                $(document).ready(function(){ $('input[type=text].datepicker_field').datepicker(datepicker_settings()); })

                update_day_names();
            },
            on_select: function (callback) {
                on_select_callbacks.push(callback);
            }
        };
    }();

}(jQuery));
