
function travelOK(dt){
    now = timeHandler.serverNow();
    if(dt.stripTime().getTime() == now.stripTime().getTime()) return false;
    var PSThour = now.getUTCHours()-8;
    if(PSThour < 0) PSThour = 24+PSThour;
    if(dt.addDays(-1).stripTime().getTime() == now.stripTime().getTime() && PSThour>=17) return false;
    return true;
}

timeHandler = {
    serverLoad: new Date(),
    loadTime: new Date(),
    now: function() {
        return new Date();
    },
    serverNow: function(){
        var ret = new Date();
        ret.setTime(this.serverLoad.getTime()+(this.now().getTime()-this.loadTime.getTime()));
        return ret;
    }
}
timeHandler.serverLoad.setTime(1215254570950.83);


var usStates = [{Code:'AL',Region:'S',Name:'Alabama'},{Code:'AK',Region:'A',Name:'Alaska'},{Code:'AZ',Region:'W',Name:'Arizona'},{Code:'AR',Region:'S',Name:'Arkansas'},{Code:'CA',Region:'W',Name:'California'},{Code:'CO',Region:'W',Name:'Colorado'},{Code:'CT',Region:'E',Name:'Connecticut'},{Code:'DE',Region:'E',Name:'Delaware'},{Code:'DC',Region:'E',Name:'District of Columbia'},{Code:'FL',Region:'S',Name:'Florida'},{Code:'GA',Region:'S',Name:'Georgia'},{Code:'HI',Region:'H',Name:'Hawaii'},{Code:'ID',Region:'W',Name:'Idaho'},{Code:'IL',Region:'M',Name:'Illinois'},{Code:'IN',Region:'M',Name:'Indiana'},{Code:'IA',Region:'M',Name:'Iowa'},{Code:'KS',Region:'M',Name:'Kansas'},{Code:'KY',Region:'M',Name:'Kentucky'},{Code:'LA',Region:'S',Name:'Louisiana'},{Code:'ME',Region:'E',Name:'Maine'},{Code:'MD',Region:'E',Name:'Maryland'},{Code:'MA',Region:'E',Name:'Massachusetts'},{Code:'MI',Region:'M',Name:'Michigan'},{Code:'MN',Region:'M',Name:'Minnesota'},{Code:'MS',Region:'S',Name:'Mississippi'},{Code:'MO',Region:'S',Name:'Missouri'},{Code:'MN',Region:'W',Name:'Minnesota'},{Code:'MT',Region:'W',Name:'Montana'},{Code:'NE',Region:'M',Name:'Nebraska'},{Code:'NV',Region:'W',Name:'Nevada'},{Code:'NH',Region:'E',Name:'New Hampshire'},{Code:'NJ',Region:'E',Name:'New Jersey'},{Code:'NM',Region:'W',Name:'New Mexico'},{Code:'NY',Region:'E',Name:'New York'},{Code:'NC',Region:'S',Name:'North Carolina'},{Code:'ND',Region:'M',Name:'North Dakota'},{Code:'OH',Region:'M',Name:'Ohio'},{Code:'OK',Region:'M',Name:'Oklahoma'},{Code:'OR',Region:'W',Name:'Oregon'},{Code:'PA',Region:'E',Name:'Pennsylvania'},{Code:'RI',Region:'E',Name:'Rhode Island'},{Code:'SC',Region:'S',Name:'South Carolina'},{Code:'SD',Region:'M',Name:'South Dakota'},{Code:'TN',Region:'S',Name:'Tennessee'},{Code:'TX',Region:'S',Name:'Texas'},{Code:'UT',Region:'W',Name:'Utah'},{Code:'VT',Region:'E',Name:'Vermont'},{Code:'VA',Region:'S',Name:'Virginia'},{Code:'WA',Region:'W',Name:'Washington'},{Code:'WV',Region:'S',Name:'West Virginia'},{Code:'WI',Region:'M',Name:'Wisconsin'},{Code:'WY',Region:'W',Name:'Wyoming'},{Code:'VI',Region:'C',Name:'U.S. Virgin Islands'},{Code:'PR',Region:'C',Name:'Puerto Rico'},{Code:'AP',Region:'',Name:'Armed Forces Pacific'},{Code:'AA',Region:'',Name:'Armed Forces Americas'},{Code:'AE',Region:'',Name:'Armed Forces Europe'}]
var caProvinces = [{Code:'AB',Name:'Alberta'},{Code:'BC',Name:'British Columbia'},{Code:'MB',Name:'Manitoba'},{Code:'NB',Name:'New Brunswick'},{Code:'NL',Name:'Newfoundland and Labrador'},{Code:'NT',Name:'Northwest Territories'},{Code:'NS',Name:'Nova Scotia'},{Code:'NU',Name:'Nunavut'},{Code:'ON',Name:'Ontario'},{Code:'PE',Name:'Prince Edward Island'},{Code:'QC',Name:'Quebec'},{Code:'SK',Name:'Saskatchewan'},{Code:'YT',Name:'Yukon'}]


validate = {
    errPage: null,
    form: null,
    logErr: function(msg, obj){
        if(!validate.errPage||!validate.form) return false;
        if(!obj)obj='';
        Ajon.Log(validate.errPage,msg,'obj='+escape(obj)+'&'+$(validate.form).serialize());
        return false;
    },
    city: function(c,d,l,ab){
        //c: cityBox string, d: city descriptor string, l: leg int (optional), ab: allow blank bool (optional)
        if(!$(c) || !$(c+'_code')){console.error(c + ' does not exist');return false;}
        if(!ab||(ab&&$F(c)!='')){
            if(!this.genericEmpty(c,
                !l?'You must provide a {0} city.'.format(d):'You must provide a {0} city for flight {1}.'.format(d,l))) 
                return false;
            if(!this.generic($F(c+'_code')=='',
                !l?'The {0} city is not recognized.'.format(d):'The {0} city for flight {1} is not recognized.'.format(d,l),c))
                return false;
        }
        return true;
    },
    date: function(dt,d,l,dc,d2,l2,sd){
        //dt: datebox string, d: date descriptor string, l: leg int (optional -- use null to not include),
        //dc: date compare string (optional -- must have d2 and l2), d2/l2 (optional): same as d/1 but for compared date
        //sd: true--allow same day bookings
        if(!$(dt)){
            console.error(dt + ' does not exist.');
            return false;
        }
        if(!this.genericEmpty(dt,
            !l?'You must provide a {0} date.'.format(d):'You must provide a {0} date for flight {1}.'.format(d,l)))
            return false;
        if(!this.generic(!$F(dt).match(/^\d{1,2}\/\d{1,2}\/(\d{2}|\d{4})$/gm),
            !l?'The {0} date you entered is invalid or in the wrong format. Please use the format MM/DD/YYYY.'.format(d):'The {0} date you entered for flight {1} is invalid or in the wrong format. Please use the format MM/DD/YYYY.'.format(d,l),dt))
            return false;
        var dt1=new Date(Date.parse($F(dt)));
        if(!this.generic(dt1>timeHandler.serverNow().addDays(330),
            !l?'Travel can only be booked up to 330 days in advance.  It is too early to book this {0} date.'.format(d):'Your {0} date for flight {1} must fall within the next 330 days.'.format(d,l),dt))
            return false;
        if(!sd&&!this.generic(!travelOK(dt1),'We\'re sorry, but departure dates this close-in cannot be booked on-line. Please call our Customer Support Center at 1-800-CHEAP-AIR (1-800-243-2724) for assistance.',dt)) return false;
        if(dc){
            var dt2=new Date(Date.parse($F(dc)));
            if(!this.generic(dt1<dt2,
                !l?'Your {0} date must fall after your {1} date.'.format(d,d2):'Your {0} date for flight {1} must fall after your {2} date for flight {3}.'.format(d,l,d2,l2),dt))
                return false;
        }
        return true;
    },
    passengers: function(p){
        //p: array of passanger field strings
        //      format: {f:fileName, d:description}
        var total=0;
        for(var i=0;i<p.length;i++){
            if($(p[i].f)){
                if(!this.genericNumber(p[i].f,'You must provide the number of {0} traveling.'.format(p[i].d),
                'The number of {0} traveling is invalid.'.format(p[i].d),true)) return false;
                total+=parseInt($F(p[i].f));
            }
        }
        if(!this.generic(total==0,'You must specify at least one passenger.',p[0].f)) return false;
        if(!this.generic(total>9,'We\'re sorry, but requests for more than 9 passengers are not supported. To book 10 or more passengers, please divide your party into groups of 9 or less.',p[0].f)) return false;
        return true;
    },
    email: function(e){
        //e: email field string
        if(!this.genericEmpty(e,'You must provide an e-mail address.')) return false;
        if(!this.generic(!$F(e).match(/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/),'"{0}" is not a valid e-mail address.'.format($F(e)),e))
            return false;
        return true;
    },
    state: function(s,c){
        //s: statefield
        //c: country string
        if(c.toUpperCase()!='US'&&c.toUpperCase()!='CA') return true;
        if(!this.generic($F(s)=='',c.toUpperCase()=='US'?'You must provide a state code.':'You must provide a province code.',s)) return false
        for(var st=0; st<usStates.length;st++){
            if($F(s)==usStates[st].Code) return true;2
        }
        for(var pr=0; pr<caProvinces.length;pr++){
            if($F(s)==caProvinces[pr].Code) return true;
        }
        return this.generic(true,c.toUpperCase()=='US'?'"{0}" is invalid.  Please enter a valid two letter state code.'.format($F(s)):'"{0}" is invalid.  Please enter a valid two letter province code.'.format($F(s)),s);
    },
    zip: function(z,c){
        //z: zip field
        //c: country string
        if(c.toUpperCase()!='US'&&c.toUpperCase()!='CA') return true;
        var cType = ['zip','postal']; 
        var cn = c.toUpperCase()=='US'?0:1;
        if(!this.genericEmpty(z,'You must provide a {0} code.'.format(cType[cn]))) return false;
        if(!this.generic(!$F(z).match(cn==0?/^\d{5}(-{1}\d{4})?$/:/^\D{1}\d{1}\D{1}[\s-]?\d{1}\D{1}\d{1}$/),'"{0}" is not a valid {1} code.'.format($F(z),cType[cn]),z)) return false; 
        return true;
    },
    name: function(n,d,ab){
        //n: name field
        //d: descriptor
        //ab: allow blanks boolean
        if(!ab&&!this.genericEmpty(n,'You must provide a first and last name.'.format(d))) return false;
        if(!this.generic(!$F(n).match(ab?/^[A-Za-z\s]*$/:/^[A-Za-z\s]{2,}$/),'"{0}" is not a valid {1} name.  Only alphabetic characters and spaces are allowed.  First and last names must be at least two letters.'.format($F(n),d),n)) return false;
        return true;
    },
    phone: function(p,intl){
        //p: phone field
        //intl: international phone? bool
        var usCA = !intl;
        if(!this.genericEmpty(p,'You must provide a phone number.')) return false;
        if(!intl&&!this.generic(!$F(p).match(/^\d{3}-\d{3}-\d{4}$/),'"{0}" is not a valid phone number.  Please be sure you are including the area code and enter the number in the format "###-###-####".'.format($F(p)),p)) return false;
        if(intl&&!this.generic($F(p).replace(/\D/gi,'').length<6,'"{0}" is not a valid phone number.'.format($F(p)),p)) return false;
        return true;
    },
    fax: function(f){
        //f: fax field
        if(!this.genericEmpty(f,'You must provide a fax number.')) return false;
        if(!this.generic(!$F(f).match(/^\d{3}-\d{3}-\d{4}$/),'"{0}" is not a valid fax number.  Please be sure you are including the area code and enter the number in the format "###-###-####".'.format($F(f)),f)) return false;
        return true;
    },
    taxID: function(t){
		//t: taxID number field
		var r=$F(t).replace(/\D/gi,'');
		if(!this.genericEmpty(t,'You must provide a tax identification number.')) return false;
		if(!this.generic(r.length!=9, '"{0}" is not a valid 9 digit tax identification number.'.format($F(t)),t)) return false;
		return true;
    },
    generic: function(x,m,f){
        //x: expression to validate
        //m: message to output on false
        //f: field to focus
        if(x){
            if(this.errPage&&this.form){
                this.logErr(m,f);
            }
            Dialog.warn({msg:m, evtClose:function(){ $(f).focus();} });
            return false;
        }
        return true;
    },
    genericEmpty: function(f,m,d){
        //f: form field to check
        //m: empty message
        //d: dropdown (bool) sets focus to f+"Arw" rather than f
        if(!this.generic($F(f)=='',m,f+(d?'Arw':''))) return false;
        return true;
    },
    genericNumber: function(f,em,im,az){
        //f: form field
        //em: empty message
        //im: invalid message
        //az: allow zeros
        if(!this.genericEmpty(f,em,false)) return false;
        if(!this.generic(!$F(f).match(/^\d{1}$/gm)||(!az&&$F(f)=='0'), im, f)) return false;
        return true;
    },
    airF:false,
    airSearch: function(f){
		if(f)validate.airF=f;
		else f=validate.airF;
        if(!this.city('from1','departure',(TripType.getType()=='M')?1:null)) return false;
        if(!this.city('to1','destination',(TripType.getType()=='M')?1:null)) return false;
        if(!($('flex') && $('flex').checked) && !this.date('dt1', 'departure',(TripType.getType()=='M')?1:null)) return false;

        if(TripType.getType()=="R") {
            if(!($('flex') && $('flex').checked) && !this.date('rdt','return',null,'dt1','departure')) return false;
        }else if (TripType.getType()=="M"){
            if(!this.city('from2','departure',2)) return false;
            if(!this.city('to2','destination',2)) return false;
            
            if(!($('flex') && $('flex').checked) && !this.date('dt2','departure',2,'dt1','departure',1)) return false;
            
            if(TripType.getLegs()>=3){
                if(!this.city('from3','departure',3)) return false;
                if(!this.city('to3','destination',3)) return false;
            
                if(!($('flex') && $('flex').checked) && !this.date('dt3','departure',3,'dt2','departure',2)) return false;
            }
            
            if(TripType.getLegs()>=4){
                if(!this.city('from4','departure',4)) return false;                        
                if(!this.city('to4','destination',4)) return false;

                if(!($('flex') && $('flex').checked) && !this.date('dt4','departure',4,'dt3','departure',3)) return false;
            }
        }
        var p=[{f:'adults',d:'adults'},  
          {f:'seniors',d:'seniors'},
          {f:'children',d:'children'},
          {f:'infants',d:'infants in seats'},
          {f:'infantsLap',d:'infants in laps'}];
        if(!this.passengers(p)) return false;
        if($('seniors')&&$('infants')&&$('infantsLap')&&!this.generic(parseInt($F('adults'))+parseInt($F('seniors'))< parseInt($F('infants'))+parseInt($F('infantsLap')),'There must be at least one adult or senior for each infant.','adults')) return false;
        
        if($('flex') && $('flex').checked){
			if(!from1Obj.rgn.value.match(/^US48|ALSK|HAWI$/gm)||!to1Obj.rgn.value.match(/^US48|ALSK|HAWI|CAND$/gm)){
			Ajon.Log('FT.INTL','International fare tracker.','A1='+escape(from1Obj.code.value)+'&T1='+escape(from1Obj.rgn.value)+'&A2='+escape(to1Obj.code.value)+'&T2='+escape(to1Obj.rgn.value));
			Dialog.warn({msg:'We\'re sorry but flexible date searches are only valid for itineraries originating in the U.S. and flying to the U.S. or Canada.  To check fares on this route, please do a standard search (with exact travel dates) instead of a flexible date search.', width:550});
			return false;
			}
            document.location.href='/air/track/?s=home&req='+escape(from1Obj.code.value+to1Obj.code.value);
            return false;
        }

        f.action = '/air/Default.htm?rt='+TripType.getType();
        return true;
    },
	hotelSearch:function(){
		if($('searchType')){
			if($('searchType').value=="city"){
				if(!validate.city('dest','destination')) return false;
			}
			else if($('searchType').value=="address"){
				if(!validate.genericEmpty('street','You must provide a street address.')) return false;
				if(!validate.genericEmpty('city','You must provide a {0} city.'.format(''))) return false;
				if(!validate.zip('zip', 'US')) return false;
			}
			else if($('searchType').value=="airport"){
				if(!validate.genericEmpty('dest_ap', 'The airport entered is not valid.')) return false;
			}			
		}
		else {
			if(!validate.city('dest','destination')) return false;
		}
        if(!validate.date('dt1', 'check-in',null,null,null,null,true)) return false;
        if(!validate.date('dt2', 'check-out', null, 'dt1', 'check-in',null,true)) return false;
        if(!validate.generic($F('dt1')==$F('dt2'),'You must stay at least one day.','dt2')) return false;
        if(!validate.genericNumber('nr','You must provide a number of rooms.',
        'The nubmer of rooms provided is not valid.', false)) return false;
        if(!validate.generic($F('nr')/1>4, 'We\'re sorry, but we can only accept hotel requests for up to 4 rooms at a time.', 'nr')) return false;
        if(!validate.genericNumber('na','You must provide a number of {0}.'.format('adults'),
        'The number of {0} is not valid.'.format('adults'), false)) return false;
        if(!validate.generic($F('na')/1>4, 'You cannot book rooms for more than 4 {0} at one time.'.format('adults'), 'na')) return false;
        if(!validate.genericNumber('nc','You must provide a number of {0}.'.format('children'),
        'The number of {0} is not valid.'.format('children'), true)) return false;
        if(!validate.generic($F('nc')/1>4, 'You cannot book rooms for more than 4 {0} at one time.'.format('children'), 'nc')) return false;
        return true;
    }    
}