(function($, $C) {

    var log, SearchForm;

    $C.Searchform = function(options) {
        $.extend(true, this, options);
        log = $.logger('ADT.Controllers.Searchform');
        SearchForm = $.$('#searchformModel');
    };

    $.extend($C.Searchform.prototype, {
        init: function(event) {
            SearchForm.init(); // init the Model 

            event.v(".attachDatepickers").render();
            jQuery.validator.messages.required = "";
            jQuery.validator.addMethod("dependencyrule", function(value, element) {
                //hand off to Model for rule mplementation.
                var selector = "select[id^='" + element.id.replace(/Number.*/, "Number']:visible");
                var validationresult = SearchForm.ValidatePax({
                    adults: $.map($(selector), function(n) { return parseInt($(n).val()) }),
                    children: $.map($(selector.replace("Adult", "Child")), function(n) { return parseInt($(n).val()) }),
                    infants: $.map($(selector.replace("Adult", "Infant")), function(n) { return parseInt($(n).val()) })
                });
                if (validationresult == "ok") return true;
                alert(validationresult);
                return false;
            }, " ");
            jQuery.validator.addMethod("requiredifshown", function(value, element) { return !$(element).is(":visible") || (value != null && value != ""); }, " ");
            jQuery.validator.addMethod("date", function(value, element) { return true; }, " ");
            // add the validator to all the forms
            $("form").each(function() { $(this).validate({ onsubmit: false, errorClass: "ADT-error", errorElement: "span" }) });

            // wire history manager - rebuilds form to posted state.


            $(function() {
                if (location.hash != null &&
                location.hash != "" &&
                location.hash.substr(1, 10) != "ADT-Search") { // prevents /ADT-FlightAndHotelBookingForm/ being processed if jquery hasnt hookedup the search button yet
                    $(document).trigger('RecreateSearchForm', location.hash.replace('#', '').split("/"));
                }
                else {
                    var depairport = ADTUtil.getVisibleItem("BookLeaving").val();
                    if (depairport == undefined) return;
                    if (depairport.length == 0) return;
                    $(document).trigger('RecreateSearchForm', [null, depairport]);
                }
            });

        },

        recreateSearchForm: function(event, searchtype, departureairport, country, airport, resort, direction, directonly, depdate, retdate,
        adults, children, infants, showadvanced, accommodationname, allprices, boardoptions, flightclass, includenofrillsflights, onewayonly,
         starrating, driverage) {
            //display correct form
            if (searchtype == "FH") event.m({ search: "FlightAndHotel", direction: direction == "false" ? "In" : "Out" }).v(".showform").render();
            if (searchtype == "H") event.m({ search: "HotelOnly" }).v(".showform").render();
            if (searchtype == "F") event.m({ search: "FlightOnly", direction: direction == "false" ? "In" : "Out" }).v(".showform").render();

            if (directonly == null) {
                directonly = (ADTUtil.getVisibleItem("BookDirectFlights").length == 0 ? false : ADTUtil.getVisibleItem("BookDirectFlights").attr("checked") || false)
            } else {
                if (ADTUtil.getVisibleItem("BookDirectFlights").length > 0) {
                    ADTUtil.getVisibleItem("BookDirectFlights").attr("checked", (directonly == "true" ? "checked" : ""));
                }
            }

            // put up loading mesg in drops
            event.v(".waitCountries").render();
            event.v(".waitAirports").render();
            event.v(".waitRegions").render();

            //reset airport;
            event.m({ set: departureairport }).v(".setDeparture").render();

            // reset countries
            SearchForm.getCountries(departureairport, directonly, function(countries) {
                event.m({ options: countries, set: country })
							.v(".setCountries")
							.render(function() { // chain so we dont get a race cndn.
							    if (!country) return;
							    if (airport.length > 0
							        || ADTUtil.getVisibleItem("BookDestinationAirport").length > 0) {
							        // reset airports
							        event.v(".waitAirports").render();
							        SearchForm.getAirports(departureairport, country, directonly, function(airports) {
							            event.m({ airports: airports, set: airport })
										.v(".setAirports")
										.render();
							        });
							    }
							    if (resort.length > 0
							        || ADTUtil.getVisibleItem("BookDestinationResort").length > 0) {
							        // reset resorts
							        event.v(".waitResorts").render();
							        SearchForm.getResorts(departureairport, country, directonly, function(resorts) {
							            event.m({ resorts: resorts, set: resort })
										.v(".setResorts")
										.render();
							        });
							    }
							    //reset dates;
							    event.m({ depdate: depdate, retdate: retdate })
								.v(".resetDates").render();
							});
            });

            if (searchtype == null
                && !$("[id^=ADT-BookDirection-Out]:visible").attr("checked")
                && !$("[id^=ADT-BookDirection-In]:visible").attr("checked")) {
                $("[id^=ADT-BookDirection-Out]:visible").attr("checked", "checked");
            }

            if (adults == null) return;
            adults = adults.split(".");
            if (adults.length > 1) {
                $(".ADT-Search:visible *[id^='ADT-BookRoomLabel2']").show();
                $(".ADT-Search:visible *[id^='ADT-BookRoom2']").show();
            }
            if (adults.length > 2) {
                $(".ADT-Search:visible *[id^='ADT-BookRoomLabel3']").show();
                $(".ADT-Search:visible *[id^='ADT-BookRoom3']").show();
            }
            $.each(adults, function(i, n) { $("[id^='ADT-BookAdultNumber" + (i + 1) + "']").val(n); });

            if (!ADTUtil.isNull(children)) {
                $.each(children.split("."), function(i, n) { $("[id^='ADT-BookChildNumber" + (i + 1) + "']").val(n); });
            }
            if (!ADTUtil.isNull(infants)) {
                $.each(infants.split("."), function(i, n) { $("[id^='ADT-BookInfantNumber" + (i + 1) + "']").val(n); });
            }

            if (showadvanced == 1) { $("#ADT-BookAdvancedOptions-" + searchtype).show(); }
            if (ADTUtil.getVisibleItem("BookAccommodationName").length > 0) ADTUtil.getVisibleItem("BookAccommodationName").val(accommodationname);
            if (ADTUtil.getVisibleItem("BookAllPrices").length > 0) ADTUtil.getVisibleItem("BookAllPrices").val(allprices);
            if (ADTUtil.getVisibleItem("BookBoardOptions").length > 0) ADTUtil.getVisibleItem("BookBoardOptions").val(boardoptions);
            if (ADTUtil.getVisibleItem("BookFlightClass").length > 0) ADTUtil.getVisibleItem("BookFlightClass").val(flightclass);
            if (ADTUtil.getVisibleItem("BookIncludeNoFrillsFlights").length > 0) ADTUtil.getVisibleItem("BookIncludeNoFrillsFlights").attr("checked", (includenofrillsflights == "true" ? "checked" : ""));
            if (ADTUtil.getVisibleItem("BookOneWayOnly").length > 0) ADTUtil.getVisibleItem("BookOneWayOnly").val(onewayonly);
            if (ADTUtil.getVisibleItem("BookStarRating").length > 0) ADTUtil.getVisibleItem("BookStarRating").val(starrating);
            if (ADTUtil.getVisibleItem("BookDriverAge").length > 0) ADTUtil.getVisibleItem("BookDriverAge").val(driverage);
        },


        showsearch: function(event) {
            var search = event.params('searchtype');
            var historykey = this.getHistoryKey(search);

            event.m({ search: search }).v(".showform").render();


            $(document).trigger('RecreateSearchForm', historykey.split("/"));
        },


        toggle: function(event) {
            var panelid = event.params('panelid');
            var searchtype = event.params('searchtype');
            event.m({ panelid: panelid, searchtype: searchtype }).v(".togglepanel").render();
        },


        removeRoom: function(event) {
            var roomnumber = event.params('roomnumber');
            event.m({ roomnumber: roomnumber }).v(".removeRoom").render();
        },

        addRoom: function(event) {
            event.v(".addRoom").render();
        },


        setDirectFlights: function(event) {
            //change event.target to departure drop down and re-route.
            event.target = ADTUtil.getVisibleItem("BookLeaving")[0];
            this.setCountries(event);
        },


        setOneWay: function(event) {
            var searchtype = event.params('searchtype');
            event.m({ searchtype: searchtype })
						.v(".setOneWay")
						.render();
        },


        changeDirection: function(event) {
            var searchtype = event.params('searchtype');
            var direction = event.params('direction');
            event.m({ searchtype: searchtype, direction: direction })
						.v(".changeDirection")
						.render();
        },


        setCountries: function(event) {
            var departureairport = $(event.target).val();
            var directonly = (ADTUtil.getVisibleItem("BookDirectFlights").attr("checked")) || false;
            event.v(".waitCountries").render();
            SearchForm.getCountries(departureairport, directonly, function(countries) {
                event.m({ options: countries })
						.v(".setCountries")
						.render();
                log.debug('setting Countries for %s', departureairport);
            });
        },

        routeCountryChangeEvent: function(event) {
            if (ADTUtil.getVisibleItem("BookDestinationAirport").length > 0)
                this.setAirports(event);
            else
                this.setResorts(event);
        },


        setAirports: function(event) {
            var searchtype = event.params('searchtype');
            var country = $(event.target).val();
            var directonly = (searchtype == "C") ? false : ((ADTUtil.getVisibleItem("BookDirectFlights").attr("checked")) || false);

            var departureairport = (searchtype == "C") ? "-" : ADTUtil.getVisibleItem("BookLeaving").val();
            event.m({ searchtype: searchtype }).v(".waitAirports").render();
            SearchForm.getAirports(departureairport, country, directonly, function(airports) {
                event.m({ airports: airports })
						.v(".setAirports")
						.render();
                log.debug('setting Airports for %s', country);
            });
        },

        setResorts: function(event) {
            var searchtype = event.params('searchtype');
            var country = $(event.target).val();
            var directonly = (ADTUtil.getVisibleItem("BookDirectFlights").attr("checked")) || false;
            var departureairport = ADTUtil.getVisibleItem("BookLeaving").val();
            event.m({ searchtype: searchtype }).v(".waitResorts").render();
            SearchForm.getResorts(departureairport, country, directonly, function(resorts) {
                event.m({ searchtype: searchtype, resorts: resorts })
						.v(".setResorts")
						.render();
                log.debug('setting Resorts for %s', country);
            });
        },

        updateReturnDate: function(event) {
            var sourcepicker = $(event.target);
            var targetpicker = $("#" + event.target.id.replace("Leaving", "Returning"));
            var sourcedate = sourcepicker.datepicker("getDate");
            var extradays = 7; // we should put this in config- maybe it should vary by search type

            var minDate = sourcedate.clone();

            if (!ADTUtil.isNull(targetpicker.attr("rel"))) {
                minDate = minDate.add(1).day();
            }

            event.m({ targetpicker: targetpicker,
                returndate: { d: sourcedate.getDate() + extradays, m: sourcedate.getMonth(), y: sourcedate.getFullYear() },
                mindate: { d: minDate.getDate(), m: minDate.getMonth(), y: minDate.getFullYear() }
            })
                .v(".updateReturnDate").render();
            log.debug('updateReturnDate for %s', targetpicker.id);
        },

        checkReturnDate: function(event) {
            var sourcepicker = $(event.target);
            // might need to check the search TYPE
            if (sourcepicker.datepicker("getDate") == sourcepicker.datepicker("option", "minDate")) {
                //todo - need to throw a dialog to advise same depart and return dates.
                event.v(".checkReturnDate").render();
            }
        },


        search: function(event) {
            var panelid = event.params("panelid");  // need this for combo search
            var formcontainerid = ".ADT-SearchPanel:visible";

            //validate - check init above and look in model for pax rules.
            if (!$("form:has(.ADT-Search:visible)").valid()) return;

            // bug fix - hard coded for the flight-only one-way case:
            var oneWay = ("#ADT-BookOneWayOnly-F:visible");
            if ($(oneWay).length != 0 && $(oneWay).attr('checked')) {
                $(oneWay).attr('value', 'on');
            }

            var st = new Array();
            var me = $(this);
            $(formcontainerid + " input[id^=ADT], " + formcontainerid + " select[id^=ADT]").each(function() {
                if (
                ($(this).val() == "on" && this.checked)
                || ($(this).val() != null && $(this).val() != ""
                    && $(this).val() != 0 && $(this).val() != "on"
                    && (!$(this).is("[type=radio],[type=checkbox]") || this.checked)
                )
            ) {
                    var ctrl = $(this);
                    var name = this.name;
                    var value = ctrl.val();
                    if (ctrl.is("[datetimeformat]")) value = GetDateFromDateTimePicker(ctrl, "/");
                    var text = (name.indexOf("$") < 0) ? "" : $.trim(ctrl.children("option:selected").text())
                    st.push(name.replace("_", value.replace(" ", "-")).replace("$", text.replace(" ", "+")));
                }
            });
            st.sort();
            st = $.map(st, function(s) { return s.split(":")[1] });
            var str = st.join("+");

            str = str.replace(/(\+for-(.)-adults,)+/g, "+for-" + $.map(ADTUtil.getVisibleItem("BookAdultNumber"), function(i) { return $(i).val(); }).join(".") + "-adults,");
            str = str.replace(/(\+and-(.)-children,)+/g, "+and-" + $.map(ADTUtil.getVisibleItem("BookChildNumber"), function(i) { return $(i).val(); }).join(".") + "-children,");
            str = str.replace(/(\+and-(.)-infants,)+/g, "+and-" + $.map(ADTUtil.getVisibleItem("BookInfantNumber"), function(i) { return $(i).val(); }).join(".") + "-infants,");


            // put an entry in the history so that "back" recalls the current state, rather than the initial load state.
            //searchtype,departureairport,country,airport,resort,dd,dm,dy,ad,am,ay
            location.hash = this.getHistoryKey($(formcontainerid + " input[id^='ADT-BookDateLeaving']")[0].id.replace("ADT-BookDateLeaving-", ""));
            SearchForm.doSearch(str);
        },

        getHistoryKey: function(searchtype) {
            var depdate = GetDateFromDateTimePicker(ADTUtil.getVisibleItem("BookDateLeaving"), "-");
            var retdate = GetDateFromDateTimePicker(ADTUtil.getVisibleItem("BookDateReturning"), "-");
            var historykey =
                    searchtype + "/" +
					ADTUtil.getVisibleItem("BookLeaving").val() + "/" +
					ADTUtil.getVisibleItem("BookDestinationCountry").val() + "/" +
					(ADTUtil.getVisibleItem("BookDestinationAirport").length == 0 ? "" : ADTUtil.getVisibleItem("BookDestinationAirport").val()) + "/" +
					(ADTUtil.getVisibleItem("BookDestinationResort").length == 0 ? "" : ADTUtil.getVisibleItem("BookDestinationResort").val()) + "/" +
				    (ADTUtil.getVisibleItem("BookDirection").length == 0 ? "false" : ADTUtil.getVisibleItem("BookDirection").eq(0).attr("checked")) + "/" +
                    (ADTUtil.getVisibleItem("BookDirectFlights").length == 0 ? "false" : ADTUtil.getVisibleItem("BookDirectFlights").attr("checked") == "checked") + "/" +
                    depdate + "/" +
					retdate + "/" +
                    $.map($("[id^='ADT-BookAdultNumber']:visible"), function(i, n) { return $(i).val(); }).join(".") + "/" +
                    $.map($("[id^='ADT-BookChildNumber']:visible"), function(i, n) { return $(i).val(); }).join(".") + "/" +
                    $.map($("[id^='ADT-BookInfantNumber']:visible"), function(i, n) { return $(i).val(); }).join(".") + "/" +
                    $("[id^='ADT-BookAdvancedOptions-']:visible").length + "/" +
                    (ADTUtil.getVisibleItem("BookAccommodationName").length == 0 ? "" : ADTUtil.getVisibleItem("BookAccommodationName").val()) + "/" +
                    (ADTUtil.getVisibleItem("BookAllPrices").length == 0 ? "" : ADTUtil.getVisibleItem("BookAllPrices").val()) + "/" +
                    (ADTUtil.getVisibleItem("BookBoardOptions").length == 0 ? "" : ADTUtil.getVisibleItem("BookBoardOptions").val()) + "/" +
                    (ADTUtil.getVisibleItem("BookFlightClass").length == 0 ? "" : ADTUtil.getVisibleItem("BookFlightClass").val()) + "/" +
                    (ADTUtil.getVisibleItem("BookIncludeNoFrillsFlights").length == 0 ? "" : ADTUtil.getVisibleItem("BookIncludeNoFrillsFlights").attr("checked") == "checked") + "/" +
                    (ADTUtil.getVisibleItem("BookOneWayOnly").length == 0 ? "" : ADTUtil.getVisibleItem("BookOneWayOnly").attr("checked") == "checked") + "/" +
                    (ADTUtil.getVisibleItem("BookStarRating").length == 0 ? "" : ADTUtil.getVisibleItem("BookStarRating").val()) + "/" +
                    (ADTUtil.getVisibleItem("BookDriverAge").length == 0 ? "" : ADTUtil.getVisibleItem("BookDriverAge").val());
            return historykey;
        }

    });

    var GetDateFromDateTimePicker = function(datepickerInput, separator) {
        if (datepickerInput != null && datepickerInput.length != 0 && datepickerInput.datepicker != null) {
            var selectedDate = datepickerInput.datepicker("getDate");
            if (selectedDate != null) return selectedDate.toString("dd" + separator + "MM" + separator + "yyyy");
        }
        return null;
    }

})(jQuery, ADT.Controllers);
            

