;/**
 *  Filename:				et.flights.js
 *  Date Created:			5/04/2011
 *  Date Modified:		    6/04/2011
 *  @author:				rollsd (implemeneted to ET by dowdy)
 *  Dependencies:			FCL library
 *  Description:			This file controls the behaviour of the fareinfo/altitude combined search form
 *  Usage:					Call ET.FLIGHTS.init( '#formId' ) after form has loaded on page
 *  Copyright:				� 2011, Flight Centre Ltd. All rights reserved.
 */
ET.FLIGHTS =
{
    $form: null,

    IATACODES: {},

    autoComplete: [],

    fieldMappings:
    {
        destStr: 'To',
        depDate: 'Departing date',
        retDate: 'Returning date'
    },

    fareinfoHost: window.location.protocol +'//'+ window.location.host,

    // fareinfo URL
    fareinfoURL: '/travel/flight-booking/results?site=et&faretype=M&todaysDate={todaysDate}&routeType={routeType}&depDate={departureDate}&retDate={returnDate}&depCode={depCode}&depStr={depStr}&destStr={destStr}&destCode={destCode}&cabinClass={cabinClass}&currCode=AUD',

    // These values store the data required for Fareinfo searches,
    // and can be passed in when rendering the fareinfoURL above
    searchData: {
        //shared values
        todaysDate: FCL.DATETIME.todaysDate(),
        destCode: '',
        destStr: '',
        departureDate: '',
        returnDate: '',
        depStr: '',
        depCode: '',

        //fareinfo specific
        routeType: 'RT',
        cabinClass: 'Y'
    },

    options:
    {
        destinations: 'all',
        defaultDestination: '',  // default destination IATA
        months: 3  // the number of months that the datepickers should show
    },

     /**
     *  @description Initialises ET.FLIGHTS functionality
     *  @param {String} formId the forms id (as jQuery selector eg '#formId')
     *  @param {object} opts (optional) options to pass in to override defaults (for future use)
     */
    init: function(formId, opts)
    {
        var _this = this;

        this.$form = $(formId);

        if(typeof opts !== 'undefined')
        {
           $.extend(this.options, opts);
        }


       this.getCitiesFromUrl();

       if(_this.$form.find('input[name=destStr]').length>0)
       {
            _this.setupAutocompleteObject();
       }
       this.setupValidation();


       if( $.browser.msie && parseInt($.browser.version) <8 )
       {
            // stops "operation aborted" issue in some situations.
            $(window).load( function(){ _this.setupForm() });
       }
       else
       {
            this.setupForm();
       }
    },

    leftColFormSwitcherInit: function()
    {
        $('#flightsLeftColumnChooser').bind('submit', function(e) { e.preventDefault(); });

        $($('#flightsLeftColumnChooser').find('option').not(':selected').val()).hide();

        $('#flightsLeftColumnChooser select').bind('change', function()
        {
            var selected = $(this).find('option:selected');
            var unSelected = $(this).find('option').not(':selected');

            $(unSelected.val()).hide();
            $(selected.val()).show();
        });
    },

    /**
     *  @description Checks the URL for certain parameters that can set the departing and
     *   returning cities, and then sets them if necessary.
     */
    getCitiesFromUrl: function()
    {
        var urlVars = FCL.UTIL.getUrlVars();
        var destination = urlVars['destination'] || urlVars['destinationCityCode'];
        var origin = urlVars['departureCity'];

        if(typeof destination !== 'undefined')
        {
           this.$form.field('destStr',destination);
           // check if an IATA code has been supplied
           if( (/^\w{3}$/).test(destination) )
           {

                this.options.defaultDestination = destination;
                this.$form.field('destCode',destination);

           }
        }

        if(typeof (origin) !== 'undefined')
        {
            if( (/^\w{3}$/).test(origin) )
            {
                this.$form.find('select[name=depCode]').val(origin);
            }
            else
            {
                this.$form.find('select[name=depCode] option').each(function(i,ele)
                {
                    if($(ele).html().toLowerCase() === origin.toLowerCase())
                    {
        				$(ele).attr( {selected: 'selected'} );
                    }
        		});
             }
        }
    },

    /**
     *  @description Sets up the default dates and datepickers, route-type handling
     */
    setupForm: function()
    {

        var _this = this;
        // initial search based on  URL query string
        var urlQueryObj = FCL.UTIL.getUrlVars();
        if(urlQueryObj !== '' && ( typeof urlQueryObj.depDate!='undefined' || typeof urlQueryObj.departureDate!='undefined' ) ) {
            var depDate = urlQueryObj.depDate || urlQueryObj.departureDate;
            var retDate = urlQueryObj.retDate || urlQueryObj.returnDate || urlQueryObj.GNEreturnDate;
            var depCode =  urlQueryObj.depCode   || urlQueryObj.departure;
            var destStr =  urlQueryObj.destStr   || urlQueryObj.destinationdisplay;
            var destCode = urlQueryObj.destCode  || urlQueryObj.destination || '';
            var routeType = urlQueryObj.routeType || urlQueryObj.tripTypeRadioGroup;
            var cabinClass = urlQueryObj.cabinClass;
        }

        /**
         * Set default dates and setup datepickers, BIND
         * departureDate is minimum is today
         * returnDate is maximum 300 days from now
         */

        _this.$form.field('departureDate',FCL.DATETIME.futureDateDays(14))
            .datepicker( $.extend(ET.SETTINGS.datePicker, {
                    minDate: 0,
                    numberOfMonths: _this.options.months,
                    beforeShow: function(input, inst) {
                        inst.dpDiv.css({   marginLeft: input.offsetWidth - 180 + 'px'});
                    },
                    onSelect: function(){
                        var toOffsetFromDate = FCL.DATETIME.compareDates(new Date(), FCL.DATETIME.stringToDate($(this).val()));
                        if(FCL.DATETIME.stringToDate(_this.$form.field('returnDate'))< FCL.DATETIME.stringToDate(_this.$form.field('departureDate')))
                        {
                            _this.$form.field('returnDate',_this.$form.field('returnDate')).datepicker('option', 'minDate', toOffsetFromDate.days + 1);
                        }
                        else
                        {
                            _this.$form.find('[name=returnDate]').datepicker('option', 'minDate', toOffsetFromDate.days);
                        }
                        _this.$form.validate().element(_this.$form.find('[name=returnDate]'));
                    }})
            );
        var toOffsetFromDate = FCL.DATETIME.compareDates(new Date(), FCL.DATETIME.stringToDate(_this.$form.find('[name=departureDate]').val()));
        _this.$form.field('returnDate', FCL.DATETIME.futureDateDays(21))
            .datepicker($.extend(ET.SETTINGS.datePicker, { minDate: toOffsetFromDate.days + 1, maxDate: 300,onSelect: function(){
                        _this.$form.validate().element(this);
                    }}));

        // Ensure destCode is a 3 letter IATA COde
        if(typeof(retDate)!='undefined' && destCode.length == 3)
        {
            _this.$form.field('destCode',destCode);
        }
        // Check the retrun date exists
        if(typeof(retDate)!='undefined')
        {
            _this.$form.field('returnDate',retDate);
        }
        // Check the retrun date exists
        if(typeof(depDate)!='undefined')
        {
            _this.$form.field('departureDate',depDate);
        }

                // Prefil form
        _this.$form.field('depCode',depCode);
        setTimeout( function(){_this.$form.field('destStr',destStr); } , 1000 );
        _this.$form.field('routeType',routeType);
        _this.$form.field('cabinClass',cabinClass);
        _this.$form.field('todaysDate', FCL.DATETIME.todaysDate());



        // Toggle return fields depending upon return or one way trip
        this.$form.find('[name=routeType]').bind('click', function(e)
        {
            if($(this).val() === 'OW')
            {
                _this.$form.find('input[name=returnDate]').datepicker('disable');
                _this.$form.field('routeType','OW');
            }
            else
            {
                _this.$form.find('input[name=returnDate]').datepicker('enable');
                _this.$form.field('routeType','RT');
            }
        });
        if(_this.$form.field('routeType') === 'OW'){
            _this.$form.find('input[name=returnDate]').datepicker('disable');
        }

        FCL.FORMS.replaceSubmitButton(this.$form.find('.submitButton'),'/images/general/waiting.gif');
    },

     /**
      *  @description Sets up validation
      */
    setupValidation: function()
    {
        var _this = this;

        //      departureArrivalDates method now added in ET.FORMS
        //      $.validator.addMethod('departureArrivalDates', function(value, element, params)

        $.validator.addMethod('departureDate', function(value, element, params)
        {

            var $parent = $(element).parent().parent();
            return FCL.DATETIME.stringToDate($parent.find('[name=departureDate]').val()) > FCL.DATETIME.stringToDate(FCL.DATETIME.futureDateDays(3));

        }, $.format('Departure date for international flights must be at least three days from now.'));

        $.validator.addMethod('checkInternationalDestination', function(value, element, params)
        {
            return _this.$form.field('depCode')!==_this.$form.field('destCode') && (_this.$form.field('destStr') !=='Type destination here...');
        }, $.format('Please select a valid destination. \n\nPlease refine your search.'));

        // Once validation passes, set destination to match in intDestinations object
        this.$form.validate(
        {
            rules:
            {
                routeType: 'required',
                depCode: 'required',
                departureDate:
                {
                    required: true,
                    departureDate: true
                },
                destStr:
                {
                    checkInternationalDestination: true
                },
                returnDate:
                {
                    required: true,
                    departureArrivalDates: true
                }
            },

            invalidHandler: function(e, validator)
            {
                FCL.FORMS.invalidForm(e, validator, ET.FLIGHTS.fieldMappings);
            },

             submitHandler: function(form)
            {
                var location =  '';


                // Pull data from the form and poplulate the search data (don't populate unchecked radio)
                $.each(ET.FLIGHTS.$form.find('input,select'),function(i,e)
                {
                    if( !($(e).attr('type')==='radio' && !$(e).is(':checked')) ){
                        _this.searchData[$(e).attr('name')] = $(e).val();
                    }
                    if( $(e).attr('name') === 'depCode') {
                        _this.searchData['depStr'] = $(e).find('option:selected').text();
                    }
                });
                
                location = _this.fareinfoHost + _this.fareinfoURL.render(_this.searchData);
                ET.FLIGHTS.$form.trigger('replaceSubmit');

                _this.tracking();

                // SetTimeout used to allow tracking time for tracking to complete.
                setTimeout( function(){
                    window.location = location;
                    setTimeout( function(){

                        }, 100);
                    }, 1000);

                return false;
            }

        });
    },

     /**
     *  @description Gets an autocomplete object created from the the IATACODES
     *  Each property of the object has the properties 'value', 'name' and 'search'
     *  'value' is the IATA code
     *  'name' is the display name to
     */
    setupAutocompleteObject: function(){

        var _this = this;
        var _dests = this.options.destinations;
        var _defaultCity = this.options.defaultDestination;
        var $destField = _this.$form.find('input[name=destStr]');

        if( $destField.attr('readonly')===true || $destField.is(':hidden')===true )
        {
            return;
        }

        $.ajax({
            url: '/new-media/javascript/iatacodes.js',
            dataType: 'text',
            success: function(data) {
                _this.IATACODES=$.parseJSON(data);

                // Create autosuggest list with weighting
                $.each(_this.IATACODES,function(i, val){
                    var tmpName = val.split(' - ');
                    if(tmpName.length>1){
                       tmpName = tmpName[0] +' '+  val.match(/(\(\w{3}\))/)[1];
                    }else{
                        tmpName = val;
                    }
                    // All weight 0 (no bookable flights)
                    var weighting = 0;

                    /*
                     *  Customizable destinations 'all', 'bookable', 'non-bookable' or object { 'BNE' : 'Brisbane', 'SYD' : 'Sydney' }
                     */

                    if(typeof(_dests) === "string")
                    {
                        if( _dests="all" || (_dests="non-bookable" && weighting==0) )
                       {
                            _this.autoComplete.push(  { value: val, iata: i, name: tmpName, weight: weighting  }    );
                       }
                    }
                    else if(typeof(_dests) === "object")
                    {
                        if(typeof(_dests[i])!=='undefined')
                        {
                            _this.autoComplete.push(  { value: val, iata: i, name: _dests[i], weight: weighting  }    );
                        }
                    }

                });

                // Sort the autocomplete.
                _this.sortAutoComplete();

                // Determine the default field value
                if( _defaultCity !== '')
                {
                    _this.$form.field('destCode',_defaultCity);
                    $destField.val( _this.IATACODES[_defaultCity].split('-')[0] );
                }
                else if($destField.val()==='' || $destField.val()==='Loading destinations...' )
                {
                    $destField.val('Type destination here...');
                }

                // Set default value behaviour
                $destField.focus(function(){
                    this.select();

                }).focus(
                    function(){
                        if($(this).val()==='Type destination here...')
                        {
                            $(this).val('');
                        }
                    }
                ).blur( function(){
                    if($(this).val()===''){
                        $(this).val('Type destination here...');
                    }
                    var searchDest =  { value: null, name: this.value, search: this.value } ;
                    _this.checkDestination(searchDest);
                }).change( function(){
                    _this.$form.field('destCode', '');
                });

                // setup autcomplete on document.load
                $destField.autocomplete(
                {
                    minLength: (_this.autoComplete.length >20) ? 3 : 0,
                    delay: 200,
                    source: _this.autoComplete,
                    select: function( event, ui ) {
                        $destField.val( ui.item.name );
                        var searchDest =  { value: ui.item.iata, name: ui.item.name, search: ui.item.value } ;
                        _this.checkDestination(searchDest);
                        return false;
                    }
                }).data( 'autocomplete' )._renderItem = function( $ul, item ) {
                   // This _renderItem function highlights the searched text and brings results matched at character 0 to the top
                    if($ul.find('li#matchedFromStartSeperator').length<1 )
                    {
                        $ul.append( '<li id="matchedFromStartSeperator">&nbsp;</li>' );
                    }

                    if(item.name.toLowerCase().indexOf($destField.val().toLowerCase()) ===0)
                    {
                        $li = $( "<li></li>" )
                            .data( "item.autocomplete", item )
                            .append( $( "<a></a>" ).attr({title: item.label }).html(_this.hightlightSearch(item.name,$destField.val())) );
                        $ul.find('li#matchedFromStartSeperator').before($li);
                        return $li;
                    }
                    else
                    {
                        $li = $( "<li></li>" )
                            .data( "item.autocomplete", item )
                            .append( $( "<a></a>" ).html(_this.hightlightSearch(item.name,$destField.val())) );
                        $ul.append($li);
                        return $li;
                    }
                };


                // Force checking of the booking when user presses enter.
                $destField.keyup(function(e){
                     var keyCode = parseInt(e.which,10);
                     if(keyCode ===13)
                     {
                         if (e.preventDefault)
                        {
                            e.preventDefault();
                        }
                        else
                        {
                            e.returnValue = false;
                        }

                        _this.getDestinationCode($destField.val());
                    }
                 });

                $('#loading').hide();

            }
        });
    },

    /**
    *  checkDestination
    *  Triggered when the user selects a new Destination.
    *  Determines if the user has entered a value directly we should check, and calls getDestinationCode()
    *  @param object destData - Obj with properties destData.name, destData.search , destData.value
    */

    checkDestination: function(destData){
       if(destData.value===null){
           destData = this.getDestinationCode(destData.name);
       }
       this.$form.field('destCode', destData.value);
    },

    hightlightSearch: function(s,t){
        var matcher = new RegExp("("+$.ui.autocomplete.escapeRegex(t)+")", "ig" );
        return s.replace(matcher, "<strong>$1</strong>");
    },

     /**
     *  @description Gets the destination code based on direct input (ie not via Autosuggest)
     *  @param {String} the destinationName
     *  @return {String/bool}  3 letter IATA code (if found)
     */
     getDestinationCode: function(destinationName){
        var _this = this;

        if(destinationName.length<3)
        {
            return false;
        }
        // Remove whitespace to clean up what the user entered.
        try{
            destinationName = destinationName.match(/^\s*([\w()]{3,})\s*$/)[1];
        } catch(e){
        }

        // Check if the input has been autopoluated by an Autosuggest result
        var testIATA = destinationName.match(/\(([\w()]{3})\)/);
        if(testIATA)
        {
            destinationName = testIATA[1];
        }

        // Check if user has entered a 3-digit IATA code (eg LAX)
        if(destinationName && destinationName.length===3 )
        {
            destinationName=destinationName.toUpperCase();
            if (typeof _this.IATACODES[destinationName] !== 'undefined'){
                return { value:destinationName, name:  _this.IATACODES[destinationName], search: _this.IATACODES[destinationName] };
            }
        }

        var searchLength = destinationName.length;

        // For cities where more than one airport is available we should use the 'all airports' code.
        // The IATA codes file has been formated such that this will be the airport code whose value (description) is the shortest in length
        var currentMatchLength = 1000;
        var currentMatch;

        // else check the name
        $.each( _this.IATACODES, function(i, IATA){

            if(IATA.substring(0,searchLength).toLowerCase() === destinationName.toLowerCase() ){

                var newMatchLength = IATA.length;
                if(newMatchLength<currentMatchLength){
                    currentMatchLength =newMatchLength;
                    currentMatch = { value: i, name:  IATA, search: IATA };
                }
            }
        });

        if(currentMatch!==null && typeof currentMatch!=='undefined')
        {
            return currentMatch;
        }
        return false;
     },

     /**
      * @description Takes the automcomplete list and sorts by weighting, and alphabetically.
      * @return {object} the sorted autocomplete.
      */
     sortAutoComplete: function(){

         this.autoComplete = this.autoComplete.sort(function(a,b){
            var compA = a.weight;
            var compB = b.weight;
            return (compA > compB) ? -1 : (compA < compB) ? 1 : 0;
         });
         return this.autoComplete;
     },

    /**
     * Tracking for google
     */
    tracking: function(){

        try{
            // Google Tracking
            _gaq.push([ '_trackEvent','fareinfo-event', 'depart', this.$form.field('depCode') ],
                [ '_trackEvent','fareinfo-event', 'destination', this.$form.field('destCode') ],
                [ '_trackEvent','fareinfo-event', 'departure-date', this.$form.field('departureDate') ],
                [ '_trackEvent','fareinfo-event', 'return-date', this.$form.field('returnDate') ],
                [ '_trackEvent','fareinfo-event', 'search', this.$form.field('depCode')+'-'+this.$form.field('destCode') ],
                [ '_trackEvent','fareinfo-event', 'route-type', this.$form.field('routeType') ],
                [ '_trackEvent','fareinfo-event', 'cabin-class', this.$form.field('cabinClass') ]);
        } catch(e) {
            // Tracking failed but continue regardless
        }

    }

};

(function(){
   /**
   * @description This String prototype method renders out a string by replacing references
   * to parameters inside curly brackets {} with object properties supplied to the render method
   * the original string remains unnaffected
   * @param Object data an object literal containing properties matching the target
   * @return String The rendered string
   */
   String.prototype.render = function(data){
        var tmp = this;
        if( typeof(data) === 'object')
        {
            $.each(data, function(varName, varData)
            {
                tmp = tmp.replace( new RegExp('\\{'+varName+'\\}','g'), varData);
            });
        }
        //remove all extra variables
        tmp = tmp.replace(/\{\w+\}/g, '');
        return tmp;
   };

})();
