/*global jQuery, IAD, Cookie, document
*/

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


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


IAD.travel.hotel_search_form = function ($) {
    var info, text, urls;

    var form = {
        initialize: function (data) {
            info = data.info;
            text = data.text;
            urls = data.urls;
            if (this.is_on_live_search_page()) {
                this.populate_with_values_from_cookies();
            }
            if (this.location_input_box_is_present()) {
                this.setup_location_autocomplete();
                this.remember_to_remove_areaid_if_location_changes();
            }
            if (this.datepickers_are_missing()) {
                IAD.travel.datepickers.initialize(info);
            }
            this.initialize_room_details_dropdowns();
            this.enable_form_validation_and_cookie_creation();
            this.set_default_focus();
        }
    };

    form.set_default_focus = function () {
        if ($("#new-hotel-search-link:visible").length > 0) {
            $("#new-hotel-search-link").focus();
        } else if ($("#select-destination #location:visible").length > 0) {
            $("#select-destination #location").focus();
        }
    };

    form.datepickers_are_missing = function () {
        return $("#accommodationsearch img.datepicker_trigger").length === 0;
    };

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

        var cookie = new Cookie(document, "travel", 2400, "/");
        cookie.load();
        return cookie;
    }

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

    function selected_from_date() {
        return Date.parseString($('#checkInDate').val(), info.date_format);
    }

    function selected_to_date() {
        return Date.parseString($('#checkOutDate').val(), info.date_format);
    }

    function from_date_is_set() {
        return $('#checkInDate').val() !== "";
    }

    function to_date_is_set() {
        return $('#checkOutDate').val() !== "";
    }

    function no_dates_are_set() {
        return ! from_date_is_set() && ! to_date_is_set();
    }

    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 number_of_rooms() {
        return $("#number-of-rooms-li input[type=radio]:checked").val();
    }

    function ensure_area_id_field_exists() {
        if ($("#accommodationsearch input[name=areaId]").length === 0) {
            $("<input type='hidden' name='areaId' id='areaId' value=''/>").appendTo("#accommodationsearch");
        }
    }

    function area_id_field() {
        ensure_area_id_field_exists();
        return $("#accommodationsearch input[name=areaId]");
    }

    function area_id_is_set() {
        return area_id_field().val() !== '';
    }

    function selected_rooms() {
        return $("#hotel-details .room-details:visible");
    }

    function map_to_value(index, element) {
        return $(element).val();
    }

    function extract_room_details(room_li) {
        return {
            number_of_adults: $(room_li).find(".number-of-adults").val(),
            number_of_children: $(room_li).find(".number-of-children").val(),
            children_ages: $(room_li).find(".children-ages select:visible").map(map_to_value).get()
        };
    }

    function destination_name() {
        return $('#location').val();
    }
    

    form.enable_form_validation_and_cookie_creation = function () {

        function children_age_dropdowns() {
            return $("#hotel-details .children-ages:visible select:visible");
        }

        function rooms_with_no_guests() {
            var room = extract_room_details(this);
            return room.number_of_adults === "0" && room.number_of_children === "0";
        }

        function values_below_zero() {
            return $(this).val() < 0;
        }

        function rooms_are_valid() {
            return ! selected_rooms().has_any(rooms_with_no_guests);
        }

        function ages_are_valid() {
            return ! children_age_dropdowns().has_any(values_below_zero);
        }

        function is_simple_search() {
            return form.simple_search_is_possible() && no_dates_are_set();
        }

        function destination_is_set() {
            return destination_name() !== "";
        }

        function create_validation_rules() {
            var destination_must_be_set = {
                is_valid: destination_is_set,
                elements_to_highlight: function () {
                    return $("#location");
                },
                error_message: text.destination_not_specified
            },
            from_date_must_be_set_for_advanced_search = {
                is_valid: function () {
                    return is_simple_search() || from_date_is_set();
                },
                elements_to_highlight: function () {
                    return $("#checkInDate");
                },
                error_message: text.control_departuredate
            },
            to_date_must_be_set_for_advanced_search = {
                is_valid: function () {
                    return is_simple_search() || to_date_is_set();
                },
                elements_to_highlight: function () {
                    return $("#checkOutDate");
                },
                error_message: text.control_arrivaldate
            },
            arrival_must_be_in_future = {
                is_valid: function () {
                    return is_simple_search() || selected_from_date() >= today();
                },
                elements_to_highlight: function () {
                    return $("#checkInDate");
                },
                error_message: text.arrival_not_before_today
            },
            dates_must_be_in_chronological_order = {
                is_valid: function () {
                    return is_simple_search() || dates_are_in_chronological_order();
                },
                elements_to_highlight: function () {
                    return $("#checkOutDate");
                },
                error_message: text.departure_after_arrival
            },
            childrens_ages_must_be_specified = {
                is_valid: function () {
                    return is_simple_search() || ages_are_valid();
                },
                elements_to_highlight: function () {
                    return children_age_dropdowns().filter("[value=-1]");
                },
                error_message: text.childs_age_not_specified
            },
            minimum_one_traveller_per_room = {
                is_valid: function () {
                    return is_simple_search() || rooms_are_valid();
                },
                elements_to_highlight: function () {
                    return selected_rooms().filter(rooms_with_no_guests);
                },
                error_message: text.minimum_one_traveller_pr_room
            };
            return $([
                destination_must_be_set,
                from_date_must_be_set_for_advanced_search,
                to_date_must_be_set_for_advanced_search,
                arrival_must_be_in_future,
                dates_must_be_in_chronological_order,
                childrens_ages_must_be_specified,
                minimum_one_traveller_per_room
            ]);
        }

        return function () {
            var rules = create_validation_rules(),
                validator = IAD.travel.form_validator(rules);
            validator.on_success_do(form.prepare_for_submit);
            validator.initialize("#accommodationsearch");
        };
    }();



    form.prepare_for_submit = function () {

        function destination_codes() {
            return $("#locationCodes").val();
        }

        function map_to_marshalled_single_room(index, room_li) {
            var room = extract_room_details(room_li);
            return [room.number_of_adults, room.number_of_children, room.children_ages.join(",")].join(";");
        }

        function marshalled_room_info() {
            return selected_rooms().map(map_to_marshalled_single_room).get().join("|");
        }

        function create_cookie() {
            var cookie = load_cookie();
            cookie.dN = destination_name();
            cookie.dC = destination_codes();
            cookie.dt1 = $("#checkInDate").val();
            cookie.dt2 = $("#checkOutDate").val();
            cookie.nRm = number_of_rooms();
            cookie.hRm = marshalled_room_info();
            cookie.store();
        }

        function set_form_action_url() {
            var action = "";
            if (info.is_on_object_page) {
                action = urls.hotel_object;
            } else if (! area_id_is_set()) {
                action = urls.hotel_location;
            } else if (from_date_is_set()) {
                action = urls.hotel_progress;
            } else {
                action = urls.hotel_result;
            }
            $("#accommodationsearch").attr("action", action);
        }

        return function () {
            set_form_action_url();
            create_cookie();
        };
    }();



    form.initialize_room_details_dropdowns = function () {

        function rooms() {
            return $("#hotel-details li.room-details");
        }

        function update_child_dropdown() {
            var num_children = $(this).find(".number-of-children").val();
            if (num_children === "0") {
                $(this).find(".children-ages").hide();
            } else {
                $(this).find(".children-ages").show();
                $(this).find(".children-ages select:first").focus();
                $(this).find(".children-ages select").slice(0, num_children).show();
                $(this).find(".children-ages select").slice(num_children).hide();
            }
        }

        function update_visibility_of_childrens_age_dropdowns() {
            rooms().each(update_child_dropdown);
        }

        function update_visibility_of_room_dropdowns() {
            rooms().slice(0, number_of_rooms()).show();
            rooms().slice(number_of_rooms()).hide();
        }

        return function () {
            $("#number-of-rooms-li input").click(update_visibility_of_room_dropdowns);
            $("#hotel-details .number-of-children").change(update_visibility_of_childrens_age_dropdowns);
            update_visibility_of_room_dropdowns();
            update_visibility_of_childrens_age_dropdowns();
        };
    }();



    form.is_on_live_search_page = function () {
        return $("input[name='liveSearch']").attr('value') === 'true';
    };



    form.location_input_box_is_present = function () {
        return ! $("#hotel #select-destination").is(":hidden");
    };


    form.simple_search_is_possible = function () {
        return form.location_input_box_is_present();
    };

    form.populate_with_values_from_cookies = function () {
        var cookie;

        function room_info_is_set_in_cookies() {
            return !! cookie.nRm;
        }

        function checkin_date() {
            return cookie.dt1 ? Date.parseString(cookie.dt1, info.date_format) : "";
        }

        function checkout_date() {
            return cookie.dt2 ? Date.parseString(cookie.dt2, info.date_format) : "";
        }

        function rooms() {
            return $(cookie.hRm.split('|'));
        }

        function extract_room_details(room_string) {
            var values = room_string.split(';');
            return {
                number_of_adults: values[0],
                number_of_children: values[1],
                children_ages: values[2] ? values[2].split(',') : []
            };
        }

        function set_number_of_adults_and_children(roomindex) {
            var room = extract_room_details(this), room_li = $("li.room-details").eq(roomindex);
            $(room_li).find(".number-of-adults").val(room.number_of_adults);
            $(room_li).find(".number-of-children").val(room.number_of_children);
            $(room.children_ages).each(function (childindex) {
                $(room_li).find(".children-ages select").eq(childindex).val("" + this);
            });
        }

        function check_radio_for_selected_number_of_rooms() {
            $("#number-of-rooms-li input[value=" + cookie.nRm + "]")[0].checked = true;
        }

        function set_room_info_from_cookies() {
            check_radio_for_selected_number_of_rooms();
            rooms().each(set_number_of_adults_and_children);
        }

        function checkin_date_is_in_future() {
            return checkin_date() > new Date();
        }

        function set_dates_from_cookies() {
            $("#checkInDate").val(checkin_date().format(info.date_format));
            $("#checkOutDate").val(checkout_date().format(info.date_format));
        }

        function reset_dates() {
            $("#checkInDate").val("");
            $("#checkOutDate").val("");
        }

        return function () {
            cookie = load_cookie();
            if (checkin_date_is_in_future()) {
                set_dates_from_cookies();
            } else {
                reset_dates();
            }
            if (room_info_is_set_in_cookies()) {
                set_room_info_from_cookies();
            }
        };
    }();



    form.setup_location_autocomplete = function () {

        function set_area_id_from_location_codes() {
            area_id_field().val($('#locationCodes').val().split('/',1));
        }

        function autocomplete_parameters() {
            return {
                extraParams: {flat: "1"},
                minChars: 3,
                scroll: false,
                cacheLength: 1,
                width: 400
            };
        }

        function populate_fields_with_autocomplete_data(event, data, formatted) {
            $('#locationHidden').val(data[0]);
            $('#locationCodes').val(data[1]);
            set_area_id_from_location_codes();
            this.blur(); // Removes focus, helps back button
        }

        return function () {
            set_area_id_from_location_codes();
            $('#location').autocomplete(urls.location_autocomplete, autocomplete_parameters()).result(populate_fields_with_autocomplete_data);
        };
    }();



    form.remember_to_remove_areaid_if_location_changes = function () {

        function current_location_differs_from_original_location() {
            return $("#location").val() !== $('#locationHidden').val();
        }

        function clear_area_id_and_location_codes() {
            area_id_field().val('');
            $('#locationCodes').val('');
        }

        function validate_location() {
            if (current_location_differs_from_original_location()) {
                clear_area_id_and_location_codes();
            }
        }

        return function () {
            $("#location").change(validate_location);
        };

    }();

    return form;
}(jQuery);
