/* 
 * A QSF widget
 * Revision : $Id: jquery.ui.qsf.js,v 1.10 2011/01/14 12:38:37 bozhch Exp $
 */

(function($) {
    /* global private variables */
    /**
     * @private
     */
    var tabType;
    /**
     * @private
     */
    var advancePurchase;

    $.widget("ui.qsf",
    {
        options : {
            qsfType : 'horizontal',
            psgrsMax : 9,
            agentUrl : {
                protocol : 'http',
                server : 'www.travelstoremaker.com',
                version : 'ibe',
                agentid : {
                    flights : 'vivrelejapon',
                    hotels : 'vivrelejapon',
                    hotelsTsm : 'vivrelejapon',
                    cars : 'vivrelejapon',
                    flightHotel : 'vivrelejapon',
                    flightCar : 'vivrelejapon'
                },
                cgi : 'runhttl',
                getFullAgentUrl : function(agentidType, newCgi) {
                    var cgi = this.cgi;

                    if (newCgi) {
                        cgi = newCgi;
                    }
                    return this.protocol + '://' + this.server + '/' + this.version+ '/' + this.agentid[agentidType] + '/' + cgi;
                }
            },
            displayLevel : 'full',
            acLang : 'en',
            qsfLanguage : 'en',
            tsmHotels : {
                geonameid : '',
                hotelid : '',
                addForHotDynpkgs : false,
                advancePurchase : 4,
                minResPeriod : 7,
                hotelLocation : {
                    fullName : '',
                    IATACode : ''
                }
            },
            flights : {
                advancePurchase : 4,
                minResPeriod : 7,
                useSuggestions : true,
                useAnalyticsTracker : false
            },
            hotels : {
                advancePurchase : 4,
                minResPeriod : 7,
                useSuggestions : true,
                hotelProviders : []
            },
            cars : {
                advancePurchase : 4,
                minResPeriod : 7,
                useSuggestions : true
            },
            flightHotel : {
                advancePurchase : 4,
                minResPeriod : 7,
                useSuggestions : true
            },
            flightCar : {
                advancePurchase : 4,
                minResPeriod : 7,
                useSuggestions : true
            },

            creditCardCurrency : 'EUR', // put empty string to
            // disable the "Credit
            // Card Currency" field
            debug : false,
            dateFormat: 'dd/mm/yy'
        },

        _create : function() {
            this.option(this.options);

            var self = this, $qsf = this.widget();

            var $tabs = $qsf.children('div');
            self._createTabs($qsf);

            $tabs.each(function(index, tab) {
                var $tab = $(tab);
                var tabId = $tab.attr('id');

                if (tabId == 'tabFlights') {
                    self._createFlightsTab($tab);
                }

                if (tabId == 'tabHotels') {
                    self._createHotelsTab($tab);
                }
                if (tabId == 'tabTsmHotels') {
                    self._createTsmHotelsTab($tab);
                }
                if (tabId == 'tabCars') {
                    self._createCarsTab($tab);
                }

                if (tabId == 'tabFlightsHotel') {
                    self._createFlightHotelTab($tab);
                }

                if (tabId == 'tabFlightsCar') {
                    self._createFlightCarTab($tab);
                }
            });
        },

        _init : function() {
            var self = this, o = this.options, $qsf = this.widget();

            var $tabs = $qsf.children('div');
            var $fullMode = $tabs.find('.full');

            self._addTooltips($tabs);

            if ('simple' == o.displayLevel) {
                $tabs.find('.advanced').hide();
                $fullMode.hide();
            } else if ('advanced' == o.displayLevel) {
                $fullMode.hide();
            }
        },

        _createBaseTab : function($tab, fromAc, fromH, fromIataCode, dp_outDay,
                dp_outMonth, datepicker_arr, toAc, toH, toIataCode, dp_retDay,
                dp_retMonth, datepicker_ret, geonameid, hotelid,
                dp_CinMonthHFH, dp_CinDayHFH, dp_CotMonthHFH, dp_CotDayHFH) {

            var o = this.options;
            var $form = $tab.find('form');
            var $advSearchLink = $form.find('a.advanced-search-link');
            var fields = {
                $fromCityAc : $form.find(fromAc || ''),
                $fromcityH : $form.find(fromH || ''),
                $from_iata_code_is_used : $form.find(fromIataCode || ''),
                $outDay : $form.find(dp_outDay || ''),
                $outMonth : $form.find(dp_outMonth || ''),
                $toCityAc : $form.find(toAc || ''),
                $tocityH : $form.find(toH),
                $to_iata_code_is_used : $form.find(toIataCode || ''),
                $retDay : $form.find(dp_retDay || ''),
                $retMonth : $form.find(dp_retMonth || ''),
                $datepicker_arr : $form.find(datepicker_arr || ''),
                $datepicker_ret : $form.find(datepicker_ret || ''),
                $form : $form,
                $advSearchLink : $advSearchLink,
                $hotelid : $form.find(hotelid || ''),
                $geonameid : $form.find(geonameid || ''),
                $dp_CinMonthHFH : $form.find(dp_CinMonthHFH || ''), 
                $dp_CinDayHFH : $form.find(dp_CinDayHFH || ''),
                $dp_CotMonthHFH : $form.find(dp_CotMonthHFH || ''), 
                $dp_CotDayHFH : $form.find(dp_CotDayHFH || '')
            };

            if (o.debug && window.console) {
                console.info($tab.attr('id'), fields);
            }

            return fields;
        },

        _createFlightsTab : function($tab) {
            var self = this, o = this.options;
            var flightTabFields = self._createBaseTab($tab, '#fromcityAc',
                    '#fromcityH', '#from_iata_code_is_used', '#dp_OutDayhFlights',
                    '#dp_OutMonthFlights', '#datepicker_arr', '#tocityAc',
                    '#tocityH', '#to_iata_code_is_used', '#dp_RetDayhFlights',
                    '#dp_RetMonthFlights', '#datepicker_dep');

            tabType = 'flights';
            advancePurchase = o.flights.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType);
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            flightTabFields.$advSearchLink.attr("href", advSearchLinkHref);
            flightTabFields.$form.attr('action', formUrl);

            if (o.flights.useSuggestions) {
                self._initAirAc($tab, flightTabFields);
            }

            if (o.flights.useAnalyticsTracker) {
                self._addTrackerParamsField(flightTabFields.$form);
            }

            flightTabFields.$form.append($('<input type="hidden" name="depdest" id="depdest">'));
            flightTabFields.$form.append($('<input type="hidden" name="retdest" id="retdest">'));
            
            
            
            self._initPassengersCountCheck($tab);
            self._setTripType($tab);
            self._initDatePickerField(flightTabFields, o.flights.minResPeriod);
            self._initQsfSubmitBtn(flightTabFields);
            self._addOnSubmit(flightTabFields);
            self._addFlightsValidation(flightTabFields,
                    self._errorMsgs[o.qsfLanguage].flights);
        },

        _createHotelsTab : function($tab) {
            var self = this, o = this.options;

            var hotelTabFields = self._createBaseTab($tab, '', '', '',
                    '#dp_cindayH', '#dp_cinmonthH', '#datepicker_cinH', '#hotcity',
                    '', '', '#dp_cotdayH', '#dp_cotmonthH', '#datepicker_cotH',
                    '#geonameid_h');

            tabType = 'hotels';
            advancePurchase = o.hotels.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType, 'runhttl');
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            hotelTabFields.$form.attr('action', formUrl);
            hotelTabFields.$advSearchLink.attr("href", advSearchLinkHref);

            if (o.hotels.useSuggestions) {
                self._initHotelAc($tab, hotelTabFields);
            }

            self._initDatePickerField(hotelTabFields, o.hotels.minResPeriod);
            self._addHotelsValidation(hotelTabFields,
                    self._errorMsgs[o.qsfLanguage].hotels);
        },

        _createTsmHotelsTab : function($tab) {
            var self = this, o = this.options;

            var hotelTabFields = self._createBaseTab($tab, '', '', '',
                    '#dp_cindayTsmH', '#dp_cinmonthTsmH', '#datepicker_cinTsmH',
                    '', '', '', '#dp_cotdayTsmH', '#dp_cotmonthTsmH',
                    '#datepicker_cotTsmH', '#geonameid_Tsmh', '#hotelid_Tsmh');

            tabType = 'hotelsTsm';
            advancePurchase = o.tsmHotels.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType, 'runhttl');
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            hotelTabFields.$form.attr('action', formUrl);
            hotelTabFields.$advSearchLink.attr('href', advSearchLinkHref);

            hotelTabFields.$geonameid.val(o.tsmHotels.geonameid);
            hotelTabFields.$hotelid.val(o.tsmHotels.hotelid);

            self._initDatePickerField(hotelTabFields, o.tsmHotels.minResPeriod);
            self._addHotelsValidation(hotelTabFields,
                    self._errorMsgs[o.qsfLanguage].hotels, true);
        },

        _createCarsTab : function($tab) {
            var self = this, o = this.options;

            var carsTabFields = self._createBaseTab($tab, '#pupcityAc',
                    '#pupcityH', '#from_iata_code_is_used_cars', '#dp_pupdayC',
                    '#dp_pupmonthC', '#datepicker_pup', '', '', '', '#dp_doffdayC',
                    '#dp_doffmonthC', '#datepicker_doff');

            tabType = 'cars';
            advancePurchase = o.cars.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType, 'runhttl');
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            carsTabFields.$form.attr('action', formUrl);
            carsTabFields.$advSearchLink.attr("href", advSearchLinkHref);

            if (o.cars.useSuggestions) {
                self._initCarAc($tab, carsTabFields);
            }

            self._initCreditCardCurrency($tab);
            self._initDatePickerField(carsTabFields, o.cars.minResPeriod);
            self._addCarsValidation(carsTabFields,
                    self._errorMsgs[o.qsfLanguage].cars);
        },

        _createFlightHotelTab : function($tab) {
            var self = this, o = this.options;

            var flightTabFields = self._createBaseTab($tab, '#fromcityAcFH',
                    '#fromcityHFH', '#from_iata_code_is_used_FH', '#dp_outdayFH',
                    '#dp_OutMonthFH', '#datepicker_arr_fh', '#tocityAcFH',
                    '#tocityHFH', '#to_iata_code_is_used_fh', '#dp_retdayFH',
                    '#dp_retmonthFH', '#datepicker_ret_fh', null, null,
                    '#dp_CinMonthHFH', '#dp_CinDayHFH', '#dp_CotMonthHFH', '#dp_CotDayHFH');
            //console.dir(flightTabFields.$outMonth);

            tabType = 'flightHotel';
            advancePurchase = o.flightHotel.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType);
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            flightTabFields.$advSearchLink.attr("href", advSearchLinkHref);
            flightTabFields.$form.attr('action', formUrl);

            if (o.flightHotel.useSuggestions) {
                self._initAirAc($tab, flightTabFields);
            }

            if (o.tsmHotels.addForHotDynpkgs) {
                flightTabFields.$toCityAc.val(o.tsmHotels.hotelLocation.fullName)
                        .attr('readonly', 'readonly');
                flightTabFields.$tocityH.val(o.tsmHotels.hotelLocation.IATACode);
                flightTabFields.$to_iata_code_is_used.val('Y');
            }

            self._initPassengersCountCheck($tab);
            self._setTripType($tab);
            self._initDatePickerField(flightTabFields, o.flightHotel.minResPeriod);
            self._addOnSubmit(flightTabFields);
            self._addFlightsHotelValidation(flightTabFields, self._errorMsgs[o.qsfLanguage].flightshotel);
        },
        _createFlightCarTab : function($tab) {
            var self = this, o = this.options;

            var flightTabFields = self._createBaseTab($tab, '#fromcityAcFC',
                    '#fromcityHFC', '#from_iata_code_is_used_fc', '#dp_outdayFC',
                    '#dp_OutMonthFC', '#datepicker_cf_arr', '#tocityAcFC',
                    '#tocityHFC', '#to_iata_code_is_used_fc', '#dp_retdayFC',
                    '#dp_retmonthFC', '#datepicker_cf_ret');

            tabType = 'flightCar';
            advancePurchase = o.flightCar.advancePurchase;

            var formUrl = o.agentUrl.getFullAgentUrl(tabType);
            var advSearchLinkHref = o.agentUrl.getFullAgentUrl(tabType, 'porch');

            flightTabFields.$advSearchLink.attr("href", advSearchLinkHref);
            flightTabFields.$form.attr('action', formUrl);

            if (o.flightCar.useSuggestions) {
                self._initAirAc($tab, flightTabFields);
            }

            self._initPassengersCountCheck($tab);
            self._setTripType($tab);
            self._initDatePickerField(flightTabFields, o.flightCar.minResPeriod);
            self._addFlightsValidation(flightTabFields,
                    self._errorMsgs[o.qsfLanguage].flights);
        },

        _errorMsgs : {
            en : {
                hotels : {
                    invalidPickUpCity : "No city/airport specified.\n",
                    invalidPickUpDate : "You have selected an invalid check in date.\n",
                    invalidDropOffDate : "You have selected an invalid check-out date.\n",
                    invalidPickUpMore11 : "The check-in date cannot be more than 11 months in the future.\n",
                    invalidDropOffMore11 : "The check-out date cannot be more than 11 months in the future.\n",
                    invalidDropOffBeforePickUp : "The departure date should be before the return date.\n",
                    invalidSelectRoom : "Please select room type.\n",
                    invalidRoomFirst : "Please select number of rooms first!\n",
                    // TODO to add the correct geonameid message
                    invalidGeonameId : "Invalid geonameid",
                    invalidHotelId : "Invalid hotelid"
                },
                cars : {
                    invalidPickUpCity : "You have selected an invalid pick-up city/airport.\n",
                    invalidPickUpDate : "You have selected an invalid pick-up date.",
                    invalidDropOffDate : "You have selected an invalid drop-off date.\n",
                    invalidPickUpMore11 : "The pick-up date cannot be more than 11 months in the future.\n",
                    invalidDropOffMore11 : "The drop-off date cannot be more than 11 months in the future.\n",
                    invalidDropOffBeforePickUp : "The pick-up date should be before the drop-of date.\n"
                },
                flights : {
                    invalidPickUpDate : "You have selected an invalid departure date.\n",
                    invalidDropOffDate : "You have selected an invalid return date.\n",
                    invalidPickUpCity : "Travel origin not specified. Please enter city name or airport code. \n",
                    invalidDropOffCity : "Travel destination not specified. Please enter city name or airport code. \n",
                    invalidDropOffBeforePickUp : "The departure date should be before the return date \n",
                    invalidPickUpMore11 : "The departure date cannot be more than 11 months in the future. \n",
                    invalidDropOffMore11 : "The return date cannot be more than 11 months in the future. \n"
                },
                flightshotel : {
                    invalidPickUpCity : "Travel origin not specified. Please enter city name or airport code. \n",
                    invalidDropOffCity : "Travel destination not specified. Please enter city name or airport code. \n",
                    invalidDropOffBeforePickUp : "The departure date should be before the return date \n",
                    invalidPickUpMore11 : "The departure date cannot be more than 11 months in the future. \n",
                    invalidDropOffMore11 : "The return date cannot be more than 11 months in the future. \n"
                },
                flightscars : {
                    invalidPickUpCity : "Travel origin not specified. Please enter city name or airport code.\n",
                    invalidDropOffCity : "Travel destination not specified. Please enter city name or airport code. \n",
                    invalidPickUpDate : "You have selected an invalid pick-up date.",
                    invalidDropOffDate : "You have selected an invalid drop-off date.\n",
                    invalidPickUpMore11 : "The pick-up date cannot be more than 11 months in the future.\n",
                    invalidDropOffMore11 : "The drop-off date cannot be more than 11 months in the future.\n",
                    invalidDropOffBeforePickUp : "The pick-up date should be before the drop-of date.\n"
                }
            }
        },
        /**
         * @param jQueryDomObj
         *            A collection with input elements
         * @param Function
         *            Provides advanced markup for an item
         * @param Function
         * @param Function
         *            Extra parameters for the backend.
         * @param Function
         *            Handle the result of a search event.
         * @param Object
         *            A collection with addtional events
         * @param Boolean
         *            Activates and deactivates autofill option
         */
        _initAc : function(acFields, formatItemFunc, parseFunc, extraParamsObj,
                resultFunc, events, autofill) {
            var o = this.options, self = this;
            var url;

            if (extraParamsObj.type == 'air') {
                url = o.agentUrl.getFullAgentUrl(tabType, 'airsearchlocation');
            }

            if (extraParamsObj.type == 'hotel') {
                url = o.agentUrl.getFullAgentUrl(tabType, 'hotsearchlocation');
            }

            acFields.autocomplete(url, {
                autoFill : (autofill) ? true : false,
                scroll : false,
                clearCustomInput : false,
                delay : 15,
                width : 280,
                max : 10,
                minChars : 2,
                formatItem : formatItemFunc,
                parse : parseFunc,
                extraParams : extraParamsObj,
                dataType : 'jsonp'
            }).result(function(e, item, formated, check) {
                self._putTxtCursorBeforeTextIE(this);
                resultFunc(e, item, formated, check);
            });

            if (events) {
                $.each(events, function(eventName, action) {
                    acFields.bind(eventName, action);
                });
            }
        },

        _initAirAc : function($tab, flightTabFields) {
            var self = this, o = this.options;

            var $acFields = $([]).pushStack(
                    [ flightTabFields.$fromCityAc.get(0),
                            flightTabFields.$toCityAc.get(0) ]);

            tabType = 'flights';
            var formatItem = function(data, i, n, value) {
                return data.displayname;
            };

            var parse = function(data) {
                return $.map(data, function(row) {
                    return {
                        data : row,
                        value : row.displayname,
                        result : row.displayname
                    };
                });
            };

            var extraParams = {
                'lang' : o.acLang,
                'type' : 'air'
            };

            var resultFunc = function(e, item, formated, check) {
                if (/^fromcityAc/.test(e.target.id)) {
                    flightTabFields.$fromcityH.val(item.code);
                    flightTabFields.$from_iata_code_is_used.val('Y').attr('name',
                            'from_iata_code_is_used');

                } else if (/^tocityAc/.test(e.target.id)) {
                    flightTabFields.$tocityH.val(item.code);
                    flightTabFields.$to_iata_code_is_used.val('Y').attr('name',
                            'to_iata_code_is_used');
                }
            };

            self._initAc($acFields, formatItem, parse, extraParams, resultFunc);
        },

        _initHotelAc : function($tab, ff) {
            var self = this, o = this.options;
            var $acFields = ff.$toCityAc;

            var formatItem = function(data, i, n, value) {
                return data.name + ((data.area_name) ? ', ' + data.area_name : '')
                        + ', ' + ((data.country) ? data.country : data.countrycode);
            };

            var parse = function(data) {
                return $.map(data, function(row) {
                    return {
                        data : row,
                        value : row.name,
                        result : row.name
                                + ((row.area_name) ? ', ' + row.area_name : '')
                                + ', '
                                + ((row.country) ? row.country : row.countrycode)
                    };
                });
            };

            var extraParams = {
                'lang' : o.acLang,
                provider : o.hotels.hotelProviders,
                'type' : 'hotel'
            };

            var resultFunc = function(e, item, formated, check) {
                ff.$geonameid.val(item.geoname_id);
            };

            var keyUpFunc = function(evt, request, settings) {
                if ((evt.keyCode >= 48 && evt.keyCode <= 90) || evt.keyCode === 0) {
                    ff.$geonameid.val("");
                }

                if (evt.keyCode == 8) {
                    if (!this.value.length) {
                        ff.$geonameid.val("");
                    }
                }
            };
            var blurFunc = function() {
                if (!ff.$geonameid.val()) {
                    this.value = '';
                }
            };
            var events = {
                'keyup' : keyUpFunc,
                'blur' : blurFunc
            };
            self._initAc($acFields, formatItem, parse, extraParams, resultFunc,
                    events, true);
        },
        _initCarAc : function($tab, ff) {
            var self = this, o = this.options;
            var $acFields = ff.$fromCityAc;

            var formatItem = function(data, i, n, value) {
                return data.displayname;
            };

            var parse = function(data) {
                return $.map(data, function(row) {
                    return {
                        data : row,
                        value : row.displayname,
                        result : row.displayname
                    };
                });
            };

            var extraParams = {
                'lang' : o.acLang,
                'type' : 'air'
            };

            var resultFunc = function(e, item, formated, check) {
                if ('pupcityAc' == e.target.id) {
                    ff.$fromcityH.val(item.code);
                    ff.$from_iata_code_is_used.val('Y').attr('name',
                            'from_iata_code_is_used');
                }
            };

            self._initAc($acFields, formatItem, parse, extraParams, resultFunc);
        },

        _createTabs : function($qsfConteiner) {
            var $tabs = $qsfConteiner.tabs();

            if (this.options.qsfType == 'vertical') {
                var tabs_lenght = $tabs.tabs('length');
                var $tabs_ul = $tabs.find('ul:first');
                var selector = 'li';

                if (tabs_lenght % 2) {
                    selector = 'li:lt(' + (tabs_lenght - 1) + ')';
                    $tabs_ul.find('li:last').width('98%');
                }

                $tabs_ul.find(selector).addClass('qsf-two-columns-tabs');
            }
        },
        _elevenMonthsPeriod : function(dateObj) {
            var tmpDate = new Date();
            tmpDate.setMonth(tmpDate.getMonth() + 11);
            return (dateObj < tmpDate);
        },

        _exportToDateObject : function($dayField, $monthField) {
            var day = $dayField.val();
            var month = $monthField.val();

            var advPurchDate = new Date();
            advPurchDate.setDate(advPurchDate.getDate() + advancePurchase);

            var date = new Date();
            date.setMonth(month, day);

            if (day != date.getDate() || month != date.getMonth()) {
                return null;
            } else {
                if (date < advPurchDate) {
                    date.setFullYear(advPurchDate.getFullYear() + 1);
                }
                return date;
            }
        },

        _importFromDateObject : function($dayField, $monthField, $fullDateField, dateObj) {
            var o = this.options;
            
            $dayField.val(dateObj.getDate());
            $monthField.val(dateObj.getMonth());
            $fullDateField.val($.datepicker.formatDate(o.dateFormat, dateObj));
        },

        _setDateSelectors : function($dayField, $monthField, $fullDateField, addMinRes) {
            var self = this;
            var date = new Date();
            
            date.setDate(date.getDate() + advancePurchase + addMinRes);
            self._importFromDateObject($dayField, $monthField, $fullDateField, date);
        },

        _initDatePickerField : function(ff, minResPeriod) {
            var self = this, o = this.options;
            var $dpPlaceHolders = $([]).pushStack([ ff.$datepicker_arr.get(0), ff.$datepicker_ret.get(0) ]);
            var $daysObjs = self._getDaysObjs();

            ff.$outMonth.change(function(e) {
                self._setMonthDaysNumber(e.target.value, ff.$outDay, $daysObjs);
                ff.$retMonth.val(ff.$outMonth.val());
                ff.$retMonth.triggerHandler('change');
            });

            ff.$retMonth.change(function(e) {
                self._setMonthDaysNumber(e.target.value, ff.$retDay, $daysObjs);
            });

            $($dpPlaceHolders).datepicker(
            {
                showAnim : false,
                inline : true,
                showAnim: false,
                inline: true,
                minDate : "+" + advancePurchase,
                maxDate : "+10m +4w",
                dateFormat: o.dateFormat,
                onSelect : function(dateText, inst) {
                    var selectedDate = $.datepicker.parseDate(o.dateFormat, dateText);
                    
                    // here we check if this is the departure calendar
                    if ($dpPlaceHolders.index(inst.input) === 0) {
                        self._importFromDateObject(
                                ff.$outDay, ff.$outMonth, 
                                ff.$datepicker_arr, selectedDate);
                        selectedDate.setDate(selectedDate.getDate() + minResPeriod);   
                    }
                    self._importFromDateObject(
                            ff.$retDay, ff.$retMonth, 
                            ff.$datepicker_ret, selectedDate);
                }
            });

            if(o.qsfLanguage === 'en'){
                $.datepicker.setDefaults($.datepicker.regional['']);
            }
            else {
                $.datepicker.setDefaults($.datepicker.regional[o.qsfLanguage]);
            }
            
            self._setDateSelectors(ff.$outDay, ff.$outMonth, ff.$datepicker_arr, 0);
            self._setDateSelectors(ff.$retDay, ff.$retMonth, ff.$datepicker_ret, minResPeriod);

            ff.$form.find('.ui-datepicker-trigger').addClass('ui-corner-all ui-icon');
        },
        // TODO add numpts to base tab object?
        _initPassengersCountCheck : function($tabFlights) {

            var o = this.options;
            var $numptcDropDown = $tabFlights.find("select[name^='numptc']");

            $numptcDropDown.change(function(event) {
                var passengersNum = 0;
                $numptcDropDown.find("option:selected").each(
                        function(index, option) {
                            passengersNum += parseInt($(option).val(), 10);
                        });
                if (o.psgrsMax < passengersNum) {
                    alert('Too many passengers. The maximum number is: '
                            + o.psgrsMax);
                    $(event.target).val('0');
                }
            });
        },

        _addHotelsValidation : function(ff, hotelErrorMsgs, isTsmHotels) {
            var self = this, o = this.options;
            var rTypeOk;
            var $roomNumsTypesHotel = ff.$form.find('#roomNumsTypesHotel'), $roomTypes = self
                    ._getRoomTypes($roomNumsTypesHotel), $roomNums = self
                    ._getRoomNums($roomNumsTypesHotel);

            ff.$form.submit(function(event) {
                var errorMsg = self._addFormValidationDefRulls(ff, hotelErrorMsgs);

                $roomTypes.each(function(i, $roomType) {
                    if ($roomType.value !== '') {
                        rTypeOk = 'ok';
                    }
                });

                if (rTypeOk != 'ok') {
                    errorMsg += hotelErrorMsgs.invalidSelectRoom;
                }

                if (o.useHotelSuggestions && !ff.$geonameid.val()) {
                    errorMsg += hotelErrorMsgs.invalidGeonameId;
                }

                if (ff.$hotelid.length && !ff.$hotelid.val()) {
                    errorMsg += hotelErrorMsgs.invalidHotelId;
                }

                if (errorMsg !== "") {
                    alert(errorMsg);
                    return false;
                } else {
                    return true;
                }
            });

            $roomTypes.change(function() {
                var index = $roomTypes.index(this);
                var $numSelector = $roomNums.eq(index);
                var num_rooms = parseInt($numSelector.val(), 10);

                if (!num_rooms) {
                    if ($(this).val() !== "") {
                        alert(hotelErrorMsgs.invalidRoomFirst);
                        $numSelector.focus();
                    }
                }
            });
        },
        _getRoomTypes : function($parent) {
            return $parent
                    .find("select[name^='roomtype']:not([name^='roomtypenum'])");
        },

        _getRoomNums : function($parent) {
            return $parent.find("select[name^='roomtypenum']");
        },

        _addCarsValidation : function(ff, hotelErrorMsgs) {
            var self = this;

            ff.$form.submit(function(event) {
                var errorMsg = self._addFormValidationDefRulls(ff, hotelErrorMsgs);

                if (errorMsg !== "") {
                    alert(errorMsg);
                    return false;
                } else {
                    return true;
                }
            });
        },
        /**
         * 
         * @param ff
         *            Object Form fields Object
         */
        _addFlightsValidation : function(ff, flightsErrorMsgs) {
            var self = this;

            ff.$form
                    .submit(function(event) {
                        var errorMsg = self._addFormValidationDefRulls(ff,
                                flightsErrorMsgs);
                        var isToCityAcExist = (ff.$toCityAc.length !== 0), isToCityAcEmpty = ff.$toCityAc
                                .val() === '';

                        if (isToCityAcExist && isToCityAcEmpty) {
                            errorMsg += flightsErrorMsgs.invalidDropOffCity;
                        }

                        if (errorMsg !== "") {
                            alert(errorMsg);
                            return false;
                        } else {
                            return true;
                        }
                    });
        },
        _addFlightsHotelValidation : function(ff, flightsErrorMsgs) {
            var self = this;

            ff.$form.submit(function(event) {

                var errorMsg = self._addFormValidationDefRulls(ff, flightsErrorMsgs);

                if (ff.$form.find('input[name="tocity"]').val() === "") {
                    errorMsg += flightsErrorMsgs.invalidDropOffCity;
                }

                if (errorMsg !== "") {
                    alert(errorMsg);
                    return false;
                } else {
                    return true;
                }
            });
        },

        _addFormValidationDefRulls : function(ff, eMsgs) {
            var self = this;
            var errorMsg = "";
            var isFromCityAcExist = (ff.$fromCityAc.length !== 0), isFromCityAcEmpty = ff.$fromCityAc
                    .val() === '';

            if (isFromCityAcExist && isFromCityAcEmpty) {
                errorMsg += eMsgs.invalidPickUpCity;
                ff.$fromCityAc.focus();
            }

            var outDate = self._exportToDateObject(ff.$outDay, ff.$outMonth);

            if (!outDate) {
                errorMsg += eMsgs.invalidPickUpDate;
            }

            var retDate = self._exportToDateObject(ff.$retDay, ff.$retMonth);

            if (!retDate) {
                errorMsg += eMsgs.invalidDropOffDate;
            }

            if (outDate && retDate) {

                if (!self._elevenMonthsPeriod(outDate)) {
                    errorMsg += eMsgs.invalidPickUpMore11;
                }

                if (!self._elevenMonthsPeriod(retDate)) {
                    errorMsg += eMsgs.invalidDropOffMore11;
                }

                if (outDate > retDate) {
                    errorMsg += eMsgs.invalidDropOffBeforePickUp;
                }
            }



            return errorMsg;
        },

        _addTrackerParamsField : function($form) {
            var newTrackerUrl = pageTracker._getLinkerUrl($form.attr('action'));
            var trackerParams = newTrackerUrl.split('?')[1];
            var $hiddenField = $('<input type="hidden" name="keytrack"').val(
                    escape(trackerParams));
            $form.appendChild($hiddenField);
        },
        _addTooltips : function($tabs) {
            $tabs.find('.info').tooltip({
                track : true,
                extraClass : 'ui-corner-all ui-state-highlight',
                delay : 20,
                top : -5,
                left : 20
            });
        },
        /**
         * This function manage the autocompleter fields
         * 
         * @param ff
         *            Object Form fields Object
         */
        _addOnSubmit : function(ff) {           
            ff.$form.submit(function(event) {
                if (ff.$fromCityAc.val().slice(0, 3) != ff.$fromcityH.val()) {
                    ff.$fromcityH.val(ff.$fromCityAc.val());
                    ff.$from_iata_code_is_used.removeAttr('name');
                }
                ff.$form.find('#depdest').val(ff.$fromCityAc.val());
                
                if (ff.$toCityAc.val().slice(0, 3) != ff.$tocityH.val()) {
                    ff.$tocityH.val(ff.$toCityAc.val());
                    ff.$to_iata_code_is_used.removeAttr('name');
                }
                
                ff.$form.find('#retdest').val(ff.$toCityAc.val());
                
                if(ff.$dp_CinMonthHFH.length){
                    ff.$dp_CinMonthHFH.val(ff.$outMonth.val());
                    ff.$dp_CinDayHFH.val(ff.$outDay.val());
                    ff.$dp_CotMonthHFH.val(ff.$retDay.val());
                    ff.$dp_CotDayHFH.val(ff.$retMonth.val());
                }

                ff.$fromCityAc.removeAttr('name');
                ff.$toCityAc.removeAttr('name');
            });
        },

        _putTxtCursorBeforeTextIE : function(txtInputObj) {
            if (txtInputObj.createTextRange) {
                var range = txtInputObj.createTextRange();
                range.move("character", 0);
                range.select();
            }
        },

        _getDaysObjs : function() {
            var daysArr = [];

            for (i = 1; i <= 31; i++) {
                daysArr.push('<option value="' + i + '">' + i + '</option>');
            }

            return $(daysArr.join(''));
        },

        _setMonthDaysNumber : function(selMonthNum, $daySelObj, $daysList) {
            var februaryDays;
            var thisYear = new Date().getFullYear();

            if ((thisYear % 4) && ((thisYear % 100 !== 0) || (thisYear % 400 === 0))) {
                februaryDays = 28;
            } else {
                februaryDays = 29;
            }

            var monthsDaysArr = [ 31, februaryDays, 31, 30, 31, 30, 31, 31, 30, 31,
                    30, 31 ];
            var daysToAdd = monthsDaysArr[selMonthNum];
            var $slicedDays = $($daysList.slice(0, daysToAdd));
            var tmpDay = $daySelObj.val();

            $daySelObj.children().remove();
            $daySelObj.append($slicedDays.clone());
            $daySelObj.val(tmpDay);
        },

        setLanguage : function(lngObj) {
            var self = this;
            self._errorMsgs = lngObj;
        },

        _setTripType : function($tab) {
            var o = this.options;
            var $retDateTimeSelectors = $tab.find('.retDateTimeSelectors');
            var $tripTypeField = $tab.find("select[name='triptype']");
            var outBoundFields = $retDateTimeSelectors
                    .find('select,input,button,label');

            $tripTypeField.change(function(event) {
                if ('ONEWAY' == event.target.value) {
                        $retDateTimeSelectors.hide();
                } else {
                    $retDateTimeSelectors.show();
                }
            });

            if ($tripTypeField.val() == 'ONEWAY') {
                $tripType.change();
            }
        },

        _initCreditCardCurrency : function($tab) {
            var o = this.options;
            var $ccCurrencyFields = $tab.find("select[name='cccardcurrency']");

            if (o.creditCardCurrency !== '') {
                $ccCurrencyFields.each(function(index) {
                    $tab.val(o.creditCardCurrency);
                });
            } else {
                $ccCurrencyFields.each(function(index) {
                    $tab.closest('.simple').hide();
                });
            }
        },
        _initQsfSubmitBtn: function (ff){
            ff.$form.find('#qsfSubmitButton').click(function (){
                ff.$form.submit();
            });
        },
        _setPreferdAirlines: function (ff){

        }
    });
}(jQuery));


