(function() {

function getOffsetTop(o) {
	var top = 0;
	if(o.offsetParent) {
		top = o.offsetTop;
		while(o = o.offsetParent) {
			top += o.offsetTop;
		}
	}
	return top;
}

ACC.SpecialOffer = function(datas) {
	if(!(this instanceof ACC.SpecialOffer)) {
		return new ACC.SpecialOffer(datas);
	}
	
	ACC.SpecialOffer.superclass.constructor.call(this);
	
	this.addEvents(['change']);
	this.initialize(datas);
};
ACC.extend(ACC.SpecialOffer, ACC.Observable, {
	initialize: function(datas) { 
		var that = this;
		this.cls = datas.cls || {};
		this.context = $(datas.context);
		this.height = this.context.offsetHeight;
		this.context.style.height = this.height + 'px';
		this.items = $$(datas.items);
		this.items.each(function(el) {
			el.onclick = that.click.bind(that);
			el.onmouseover = function() {
				that.mouseover(this);
			};
			el.onmouseout = function() {
				that.mouseout(this);
			};
		});
		this.lastItem = this.items[0];
		this.closeLink = document.createElement('a');
		this.closeLink.className = this.cls.close;
		this.closeLink.href = '#';
		this.closeLink.innerHTML = datas.closeTxt;
		this.limitHeight = datas.limitHeight || 50;
		this.activeIndicator = $(datas.activeIndicator);
		this.description = document.getElementById('booking-zone').getElementsByTagName('p')[0];
	},
	
	click: function(e) {
		e = e || window.event;
		var t = Event.element(e);
		var p = t.parentNode;
		var item = t;
		if($(p).hasClassName(this.cls.cgv)) {
			this.legalTxt($(p).next());
			return false;
		}
		while(item && !$(item).hasClassName(this.cls.item)) {
			item = item.parentNode;
		}
		if(item && $(item).hasClassName(this.cls.item)) {
			if(this.lastItem && this.lastItem != item) {
				this.desactivate(this.lastItem);
			}
			this.positionArrow(item);
			this.lastItem = item;
			if(p.className == this.cls.more) {
				this.open(item);
			}
			this.fireEvent('change');
			if(p.className == this.cls.book && this.description) {
				var desc = this.description.innerHTML.replace(/^([^.…]+[.…]+)/, '<strong>$1</strong>');
				this.description.innerHTML = desc;
			}
			return false;
		}
	},
	
	legalTxt: function(item) {
		$(item).toggleClassName(this.cls.hide);
	},
	
	positionArrow: function(item) {
		var top = getOffsetTop(item) - getOffsetTop(this.context);
		this.activeIndicator.style.top = top + 'px';
	},
	
	open: function(item) {
		var that = this,
			infos = item.getElementsByTagName('div')[1];
		item.style.height = this.height + 'px';
		infos.style.height = this.height - this.limitHeight + 'px';
		$(item).addClassName(this.cls.opened);
		this.closeLink.onclick = function() {
			that.close(item, infos, this);
			return false;
		};
		item.appendChild(this.closeLink);
		this.activeIndicator.style.top = '0';
	},
	
	close: function(item, infos, link) {
		infos.style.height = item.style.height = 'auto';
		$(item).removeClassName(this.cls.opened);
		var cgv = $$('#' + item.id + ' ul.cgv')[0];
		if(cgv) {
			cgv.addClassName(this.cls.hide);
			cgv = null;
		}
		link.parentNode.removeChild(link);
		this.positionArrow(item);
	},
	
	desactivate: function(item) {
		$(item).removeClassName(this.cls.active);
		this.lastItem = null;
	},
	
	activate: function(item) {
		$(item).addClassName(this.cls.active);
		this.lastItem = item;
	},
	
	mouseover: function(item) {
		if(item != this.lastItem) {
			$(item).addClassName(this.cls.active);
		}
	},
	
	mouseout: function(item) {
		if(item != this.lastItem) {
			$(item).removeClassName(this.cls.active);
		}
	}
});

ACC.BookingEngineField = function(datas) {
	if(!(this instanceof ACC.BookingEngineField)) {
		return new ACC.BookingEngineField(datas);
	}
	
	ACC.BookingEngineField.superclass.constructor.call(this);
	
	this.addEvents(['change', 'fill', 'clear']);
	this.initialize(datas);
};
ACC.extend(ACC.BookingEngineField, ACC.Observable, {
	initialize: function(datas) {
		var that = this;
		if(!datas.key) {throw new Error('ACC.BookingEngineField: key not found but required');}
		this.key = datas.key;
		if(!datas.form) {throw new Error('ACC.BookingEngineField: form not found');}
		this.form = datas.form;
		this.dom = this.form.elements[datas.field];
		if(!this.dom) {throw new Error('ACC.BookingEngineField: field not found');}
		Event.observe(this.dom, 'change', function() {that.fireEvent('change');});
		this.type = this.dom.type;
		this.group = this.dom.parentNode;
		this.hideCls = datas.hideCls;
		this.defaults = datas.defaults || null;
		this.processDatas = datas.processDatas || null;
		this.fillDirectly = (typeof datas.fillDirectly != 'undefined') ? datas.fillDirectly : true;
		this.active = false;
		//this.arrivalDate = null;
	},
		
	update: function(datas, options) {
		if(datas) {
			var h = datas.hide,
				k = this.key;
			this.clear();
			if(h && h.indexOf(k) > -1) {
				this.hide();
				return;
			} else {
				this.show();
			}
			this.rawDatas = datas;
			this.datas = datas[k] || datas;
			options = options || {};
			if(this.processDatas && typeof this.processDatas == 'function') {
				this.datas = this.processDatas(datas, options);
			}
			if(this.datas.length && this.fillDirectly) {
				this.fill(options.index);
			}
			this.fillDirectly = true;
		}
	},
	
	show: function() {
		$(this.group).removeClassName(this.hideCls);
		this.active = true;
	},
	
	hide: function() {
		$(this.group).addClassName(this.hideCls);
		this.active = false;
	},
	
	fill: function(index) {
		if(this.type == 'text') {
			
		} else if(this.type == 'select-one') {
			var d = this.defaults;
			if(d) {
				this.dom.options.length = 1;
				this.dom.options[0].innerHTML = d.fullTxt;
			} else {
				this.dom.options.length = 0;
			}
			if(this.datas.constructor == Array) {
				var k = -1, txt, val;
				while(this.datas[++k]) {
					//construction des select ville et nuits
					txt = this.datas[k].txt;
					val = this.datas[k].val || txt;
					this.dom.options[this.dom.options.length] = new Option(txt, val);
				}
				index = index || 0;
				if(typeof index != 'number' || index < 0) {
					index = 0;
				}
				if(index >= this.dom.length) {
					index = this.dom.length - 1;
				}
				this.dom.selectedIndex = index;
			}
		}
		this.fireEvent('fill');
	},
	
	clear: function() {
		if(this.type == 'text') {
			if(this.dom.defaultValue) {
				this.dom.value = this.dom.defaultValue;
			} else if(this.defaults) {
				this.dom.value = this.defaults.val;
			}
		} else if(this.type == 'select-one') {
			this.dom.options.length = 0;
			var d = this.defaults;
			if(d) {
				this.dom.options[this.dom.options.length] = new Option(d.emptyTxt, d.val);
			}
		}
		this.fireEvent('clear');
	}
});

ACC.BookingEngineCalendar = function(datas) {
	if(!(this instanceof ACC.BookingEngineCalendar)) {
		return new ACC.BookingEngineCalendar(datas);
	}
	
	ACC.BookingEngineCalendar.superclass.constructor.call(this);
	
	this.addEvents(['change', 'fill', 'clear']);
	this.initialize(datas);
};
ACC.extend(ACC.BookingEngineCalendar, ACC.Observable, {
	
	initialize: function(datas) {
		this.getElements(datas);
		Event.observe(this.arrival, 'focus', function() {this.blur();});
		this.lastNightsIndex = ACC.fields.nights.dom.selectedIndex;
		this.arrivalDate = null;
		this.departureDate = null;
		this.arrivalID = datas.arrivee;
		this.buttonID = datas.button;
		this.hideCls = datas.hideCls;
		this.period = datas.period;
		this.minDepartureDate=datas.minDepartureDate; 
		this.maxDepartureDate=datas.maxDepartureDate;
		this.specialMaxDepartureDate=datas.specialMaxDepartureDate;
		this.setSpecialMaxDepartureDate=false;

	},
	
	getElements: function(datas) {
		this.arrival = document.getElementById(datas.arrivee);
		this.day = document.getElementById(datas.day);
		this.month = document.getElementById(datas.month);
		this.year = document.getElementById(datas.year);
		if(!this.arrival || !this.day || !this.month || !this.year) {throw new Error('ACC.BookingEngineCalendar.getElements: missing element(s)');}
		this.departureHolder = document.getElementById(datas.departureHolder);
		if(this.departureHolder) {
			this.departureDayHolder = document.getElementById(datas.departureDayHolder);
			this.departureDateHolder = document.getElementById(datas.departureDateHolder);
		}
	},
	
	setMinDate: function(weekends) {
		var d = new Date(), check = true;
		if(weekends) {
			while(check) {
				cwe = Calendar.bigWeekEnd(d, d.getFullYear(), d.getMonth(), d.getDate(), ACC.fields.nights.rawDatas.nights.max, ACC.fields.nights.rawDatas.oneDayOnly, ACC.fields.nights.rawDatas.noWE);
				cP =  this.disableDates(d, d.getFullYear(), d.getMonth(), d.getDate());
				check = cwe && !cP ;
				d.setTime(d.getTime() + Date.DAY);
			}
		} 
		else {
			while(check) {
				check = this.disableDates(d, d.getFullYear(), d.getMonth(), d.getDate());
				d.setTime(d.getTime() + Date.DAY);
			}
		}
		d.setTime(d.getTime() - Date.DAY);
		this.arrivalDate = d;
		this.setCGI(d);
		this.arrival.value = d.print(Calendar._TT.DEF_DATE_FORMAT);
		this.setMaxNights(d);
	},
	disableWEDates:function(dDate, y, m, d) {
		var flag = this.disableDates(dDate, y, m, d) ;
		return flag || Calendar.bigWeekEnd(dDate, y, m, d, ACC.fields.nights.rawDatas.nights.max, ACC.fields.nights.rawDatas.oneDayOnly, ACC.fields.nights.rawDatas.noWE)
	},
	setCalendar: function(weekends) {
		var controlDates;
		if(weekends) {
			/*controlDates = function(date, y, m, d) {
				return Calendar.bigWeekEnd(date, y, m, d, ACC.fields.nights.rawDatas.nights.max, ACC.fields.nights.rawDatas.oneDayOnly, ACC.fields.nights.rawDatas.noWE);
			};*/
			controlDates = this.disableWEDates.bind(this);
			Calendar.NB_OF_NIGHTS_MAX = ACC.fields.nights.rawDatas.nights.max;
			
		} else {
			controlDates = this.disableDates.bind(this);
		}
		this.setMinDate(weekends);
		Calendar.setup({
			inputField: this.arrivalID,
			button: this.buttonID,
			button_eventNames: ['click'],
			inputField_eventNames: ['click', 'focus'],
			ifFormat: Calendar._TT.DEF_DATE_FORMAT,
			singleClick: true,
			onSelect: this.selectDate.bind(this),
			dateStatusFunc: controlDates
		});
	},
	
	selectDate: function(calendar, date) {
		if(!this.checkDate(calendar.date)) {
			return false;
		}
		if(calendar.dateClicked) {
			this.arrivalDate = calendar.date;
			this.setCGI(calendar.date);
			this.updateDepartureDate();
			this.arrival.value = date;
			calendar.hide();
			this.setMaxNights(calendar.date);
			this.fireEvent('change');
		}
		return true;
	},
	
	setCGI: function(date) {
		this.day.value = date.getDate();
		this.month.value = date.getMonth() + 1;
		this.year.value = date.getFullYear();
		if(!ACC.fields.nights.dom.value && ACC.fields.nights.rawDatas.nights.min) {
			ACC.fields.nights.dom.value = ACC.fields.nights.rawDatas.nights.min;
		}
	},
	
	disableDates: function(dDate, y, m, d) {
		var minPeriod = new Date();
		if(this.minDepartureDate && this.minDepartureDate>minPeriod){
				minPeriod=this.minDepartureDate;
			}
		if(dDate.getTime() < (minPeriod.getTime() - Date.DAY)) {
			return true;
		}
		
		var maxPeriod = new Date(minPeriod.getTime() + ((ACC.fields.nights.rawDatas.period || this.period) * Date.DAY)),
			n = (Number(ACC.fields.nights.dom.value) || 0) * Date.DAY;
		if(this.specialMaxDepartureDate){
			maxPeriod=this.specialMaxDepartureDate.dateMax;
		}
		if(this.maxDepartureDate) maxPeriod=this.maxDepartureDate;
//		if (ACC.fields.nights.rawDatas.maxDays)	maxPeriod = new Date(minPeriod.getTime() + +ACC.fields.nights.rawDatas.maxDays* Date.DAY);
		if(dDate.getTime() > (maxPeriod.getTime() - n)) {
			return true;
		}
		return false;
	},
	

	checkDate: function(date) {
		var msg, minPeriod = new Date();
	
		if(date.getTime() < (minPeriod.getTime() - Date.DAY)) {
			msg = "ACC.PromoCalendar: out of min date";
			window.calendar.setDate(minPeriod);
			return false;
		}
		var maxPeriod = new Date(minPeriod.getTime() + ((ACC.fields.nights.rawDatas.period || this.period) * Date.DAY)),
			n = (Number(ACC.fields.nights.dom.value) || 0) * Date.DAY;

	
		if((date.getTime() + n) > maxPeriod.getTime()) {
			msg = "ACC.PromoCalendar: out of max date";
			var maxDate = new Date();
			maxDate.setTime(maxPeriod.getTime() - n);
			window.calendar.setDate(maxDate);
			return false;
		}
		return true;
	},
	
	setMaxNights: function(date) {
		
		var maxPeriod = new Date(new Date().getTime() + ((ACC.fields.nights.rawDatas.period || this.period) * Date.DAY)),
			cut = Math.floor((maxPeriod.getTime() - date.getTime()) / Date.DAY),
			calDate = (typeof calendar != 'undefined') ? calendar.date : new Date(this.year.value, this.month.value - 1, this.day.value);
			
		if(this.maxDepartureDate){
			var maxPeriod = new Date(this.maxDepartureDate.getTime()),
			cut = Math.floor((maxPeriod.getTime() - date.getTime()) / Date.DAY),
			calDate = (typeof calendar != 'undefined') ? calendar.date : new Date(this.year.value, this.month.value - 1, this.day.value);
		}
		if(ACC.fields.nights.rawDatas.specialDays) {
			// assign the right number of nights
			Calendar.bigWeekEnd(calDate, calDate.getFullYear(), calDate.getMonth(), calDate.getDate(), ACC.fields.nights.rawDatas.nights.max, ACC.fields.nights.rawDatas.oneDayOnly, ACC.fields.nights.rawDatas.noWE);
			cut = Calendar.NB_OF_NIGHTS_MAX;
		}
		if(cut > 0 && ACC.fields.nights.rawDatas.nights) {
			var max = ACC.fields.nights.rawDatas.nights.max,
				index = ACC.fields.nights.dom.selectedIndex;
			if(cut < max) {
				if (ACC.fields.nights.rawDatas.nights.min && ACC.fields.nights.rawDatas.nights.min == max)
					ACC.fields.nights.update(ACC.fields.nights.rawDatas, {max: max});
				else
					ACC.fields.nights.update(ACC.fields.nights.rawDatas, {max: cut, index: index});
			} else {
				ACC.fields.nights.update(ACC.fields.nights.rawDatas, {index: index});
			}

		}
		
	},
	
	updateDepartureDate: function() {
		if(!this.showDeparture && this.departureHolder) {
			$(this.departureHolder).addClassName(this.hideCls);
			return;
		}
		if(this.showDeparture && this.arrivalDate && this.departureHolder && this.departureDayHolder && this.departureDateHolder) {
			var stay = Number(ACC.fields.nights.dom.value) * Date.DAY,
				departure = new Date();
			if(stay) {
				departure.setTime((window.calendar ? window.calendar.date.getTime() : this.arrivalDate.getTime()) + stay);
				this.departureDayHolder.innerHTML = Calendar._DN[departure.getDay()];
				var d = departure.getDate();
				d = d < 10 ? '0' + d : d;
				var m = departure.getMonth() + 1;
				m = m < 10 ? '0' + m : m;
				var y = departure.getFullYear();
				this.departureDateHolder.innerHTML = Calendar._TT.DEF_DATE_FORMAT.replace('%d', d).replace('%m', m).replace('%Y', y);
				$(this.departureHolder).removeClassName(this.hideCls);
			}
		}
	}
});

ACC.BookingEngineForm = function(datas) {
	if(!(this instanceof ACC.BookingEngineForm)) {
		return new ACC.BookingEngineForm(datas);
	}
	
	ACC.BookingEngineForm.superclass.constructor.call(this);
	
	this.addEvents(['change', 'fill', 'clear']);
	this.initialize(datas);
};
ACC.extend(ACC.BookingEngineForm, ACC.Observable, {
	initialize: function(datas) {
		this.root = document.getElementById(datas.description.root);
		if(!this.root) {
			throw new Error('ACC.BookingEngineForm.getDescriptionEls: root not found');
		}
		this.form = document.forms[datas.form];
		if(!this.form) {
			throw new Error('ACC.BookingEngineForm: form not found');
		}
		if(!datas.url || typeof datas.url != 'string') {
			throw new Error('ACC.BookingEngineForm: URL missing or not a string');
		}
		this.url = datas.url;
		this.getDescriptionEls(datas.description);
		this.getFields(datas.fields, datas.hideCls);
		this.getCalendar(datas.calendar, datas.hideCls, datas.period);
	},
	
	getDescriptionEls: function(datas) {
		this.descriptionTitle = this.root.getElementsByTagName(datas.title)[0];
		this.descriptionBody = this.root.getElementsByTagName(datas.body)[0];
		if(!this.descriptionTitle || !this.descriptionBody) {
			throw new Error('ACC.BookingEngineForm.getDescriptionEls: description not found');
		}
		root = null;
	},
	
	getFields: function(datas, hideCls) {
		ACC.fields = {};
		var d;
		hideCls = hideCls || 'hide';
		for(var i = 0, len = datas.length; i < len; i++) {
			d = datas[i];
			d.form = this.form;
			d.hideCls = hideCls;
			if(!d.key) {throw new Error('ACC.BookingEngineForm: key not found but required on field number ' + (i + 1));}
			ACC.fields[d.key] = new ACC.BookingEngineField(d);
		}
	},
	
	getCalendar: function(datas, hideCls, period) {
		datas.hideCls = hideCls;
		datas.period = period;
		this.calendar = new ACC.BookingEngineCalendar(datas);
	},
	
	update: function(index) {
		var weekdays=new Array("sun", "mon", "tue", "wed", "thu", "fri", "sat");
		if(this.error) {return;}
		var datas = this.datas[index];
		
		if(datas && index != this.current && !this.error) {
			this.current = index;
			var showpromo=true;
			if(datas.days) {
				showpromo=false;
				var offerdays = datas.days.split('|');
				if (offerdays) {
					var today = new Date();		var todaysday =	weekdays[today.getDay()]; 
					for(i=0 ; i< offerdays.length ; i++) {
						if (offerdays[i] == todaysday)
							showpromo = true;
					}
				}
				if (!showpromo) {
					// do not show offer : hide all, 
				//	$('bookingEngine').innerHTML = "pas le bon jour" ; return;
					for(var p in ACC.fields) {
						ACC.fields[p].hide();
					}
					$('dates-sejour').style.display="none";
					if($('submitbtn')) $('submitbtn').style.display="none";
					//show message
					if ($('promo-msg')) {
						if (datas.daysoffmessage ) 
							$('promo-msg').innerHTML = datas.daysoffmessage ;
						else 
							$('promo-msg').innerHTML = "not valid today" ;
						$('promo-msg').removeClassName('off');
					}
					this.datas[index].description = '' ;
					this.setDescription(index);

				}
			}
			
			if(showpromo) {
				if ($('promo-msg')) $('promo-msg').addClassName('off');
				$('dates-sejour').style.display="block";
				if ($('submitbtn')) $('submitbtn').style.display="block";
				this.setDescription(index);
				this.setParams(index);
				
				this.calendar.showDeparture = datas.showDeparture ? true : false;
				this.calendar.minDepartureDate = datas.minDepartureDate;
				this.calendar.maxDepartureDate = datas.maxDepartureDate;
				this.calendar.specialMaxDepartureDate=datas.specialMaxDepartureDate;
				// check if specialDays exist but only for weekends
				if(datas.specialDays) {
					var c = 0;
					for(var i in datas.specialDays) {
						c++;
					}
					if(!c) {
						Calendar.SPECIAL_DAYS = {};
					}
				}
				/*if(datas.specialMaxDepartureDate && this.calendar.setSpecialMaxDepartureDate) {
					this.calendar.minOri=datas.calendar.minDepartureDate;
					this.calendar.maxOri=datas.calendar.maxDepartureDate;
					this.calendar.maxDepartureDate=datas.specialMaxDepartureDate.dateMax;
					this.calendar.minDepartureDate=datas.specialMaxDepartureDate.dateMin;
				}*/
				for(var p in ACC.fields) {
					ACC.fields[p].update(datas);
				}
					this.fireEvent('change');
			}
		
		}
	},
	
	getDatas: function(index) {
		function getResponse(transport) {
			try {
				that.datas = eval('(' + transport.responseText + ')');
				that.error = null;
			} catch(e) {
				reportError('read');
			}
			that.update(index);
		}
		
		function reportError(k) {
			that.error = msg[k || 'load'];
		}
		
		this.error = null;
		var that = this,
			msg = {
				load: 'Error loading URL: ' + that.url,
				read: 'Error reading the responseText: JSON problem...'
			},
			req = new Ajax.Request(that.url, {method: 'get', onComplete: getResponse, onFailure: reportError});
	},
	
	setDescription: function(index) {
		this.descriptionTitle.innerHTML = this.datas[index].name;
		this.descriptionBody.innerHTML = this.datas[index].description;
	},
	
	setParams: function(index) {
		var params = this.datas[index].params;
		if(params) {
			var f;
			for(var p in params) {
				f = this.form.elements[p];
				if(f) {
					f.value = params[p];
				}
			}
			f = null;
		}
	}
});

// tools for this specific implementation
ACC.extend(ACC.BookingEngineForm, {
	destinationIsNotEmpty: function(field) {
		return !(/^\s*$/.test(field.value));
	},
	
	dateIsNotEmpty: function() {
		var c = this.calendar;
		return !!(c.arrival.value && c.day.value && c.month.value && c.year.value);
	},
	
	addValidation: function(fn) {
		this.addEvents(['submit']);
		var that = this;
		Event.observe(this.form, 'submit', fn);
	},
	
	resetDate: function() {
		var c = this.calendar;
		c.arrival.value = c.day.value = c.month.value = c.year.value = '';
	}
});

})();

ACC.tools.addDomReadyListener(function() {
	$(document.body).addClassName('js');
	
	var rub = 'duree-sejour|thematiques|low-cost|summer-deals|summer-pack|summer-budget|winter',
		ssRub = '1-nuit|2-nuits|1-2-nuits|3-nuits|4-nuits|decouverte|detente|degustation|sport|prestige-romance';
	var	bodyCls = document.body.className.split(' '),
		rubId = bodyCls[1],
		ssRubId = bodyCls[2],
		errors = document.getElementById('search-error');
	if(ssRubId == 'js') {ssRubId = '';}
	if(!rubId || rub.indexOf(rubId) < 0 || (ssRubId && ssRub.indexOf(ssRubId) < 0) || !errors) {return;}
	
	ssRubId = ssRubId ? '-' + ssRubId : '';

	// detect url param to check if a specific offer should be highlighted
	var url = ''+document.location;
	var promoId = url.toQueryParams().promo;
	var promoStart = 'p1';
	if (promoId && document.getElementById(promoId)){
		promoStart = promoId;
	}
	
	var form = 'bookingEngine',
		hotelOuVille = document.forms.bookingEngine.elements.hotel_ou_ville,
		msg = {
			intro: I18N._('promo.booking.errors.msg', 'Please fill in the following fields'),
			destination: I18N._('promo.booking.errors.msg', 'destination'),
			countries: I18N._('promo.booking.errors.msg', 'countries'),
			cities: I18N._('promo.booking.errors.msg', 'cities'),
			hotels: I18N._('promo.booking.errors.msg', 'hotels'),
			date: I18N._('promo.booking.errors.msg', 'check-in date')
		};
	
	var lg = function() {
		var l = document.getElementsByTagName('html')[0].lang;
		if(!l || l == 'en') {l = 'gb';}
		return l;
	};
	
	// reset value on page load (important with back button)
	hotelOuVille.value = '';
	
	// create all needed objects
	ACC.booking = ACC.BookingEngineForm({
		form: form,
		url: '/scripts-v56/promo/' + lg() + '/' + rubId + ssRubId + '.js',
		loader: 'load-booking',
		hideCls: 'hide',
		description: {
			root: 'booking-zone',
			title: 'h2',
			body: 'p'
		},
		period: 405,
		fields: [
			{
				key: 'destination',
				field: 'destination_libre'
			}, {
				key: 'countries',
				field: 'liste_pays',
				defaults: {val: '', emptyTxt: I18N._('promo.booking.defaults', 'Country'), fullTxt: I18N._('promo.booking.defaults', 'Select a country')}
			},{
				key: 'cities',
				field: 'liste_villes',
				defaults: {val: '', emptyTxt: I18N._('promo.booking.defaults', 'City'), fullTxt: I18N._('promo.booking.defaults', 'Select a city')}
			},{
				key: 'hotels',
				field: 'liste_hotels',
				defaults: {val: '', emptyTxt: I18N._('promo.booking.defaults', 'Hotel'), fullTxt: I18N._('promo.booking.defaults', 'Select a hotel')}
			},{
				key: 'nights',
				field: 'nb_nuit',
				fillDirectly: false,
				processDatas: function(datas, options) {
					if(datas.nights) {
						if(datas.nights.only){
							var d = [];
							var tabNights=(datas.nights.only).split("-");
							min = options.min || tabNights[0] || 1,
							max = options.max || tabNights[tabNights.length] || 23;
							for(var i = 0; i <tabNights.length; i++) {
								d[d.length] = {'val': tabNights[i], 'txt': tabNights[i] < 10 ? '0' + tabNights[i] : tabNights[i]};
							}
						}else{
						var d = [],
							min = options.min || datas.nights.min || 1,
							max = options.max || datas.nights.max || 23;
						for(var i = min; i <= max; i++) {
							d[d.length] = {'val': i, 'txt': i < 10 ? '0' + i : i};
						}
					}
						return d;
					}
				}
			},{
				key: 'promo',
				field: 'code_avantage'
			}
		],
		calendar: {
			arrivee: 'arrivee',
			button: 'date_arrivee_img',
			day: 'jour_arrivee',
			month: 'mois_arrivee',
			year: 'annee_arrivee',
			departureHolder: 'depart',
			departureDayHolder: 'depart_jour',
			departureDateHolder: 'depart_date'
		}
	});
	
	// change TK / eventually update departure date
	function changeNights(e) {
		ACC.booking.calendar.updateDepartureDate();
		var map = this.rawDatas.mapRA1;
		if(map) {
			var v = this.dom.value;
			if(map[v]) {
				document.forms[form].elements.RA1.value = map[v];
			}
		}
	}
	
	// validation
	var nbErrors = 0, stockErrors = {};
	
	function addErrorField(f) {
		if(msg[f] && stockErrors[f] === undefined) {
			stockErrors[f] = '<li id="error-' + f + '">' + msg[f] + '</li>';
			nbErrors++;
		}
	}
	
	function displayError(f) {
		if(nbErrors > 0) {
			var str = '<p>' + msg.intro + '</p><ol>';
			for(var i in stockErrors) {
				str += stockErrors[i];
			}
			str += '</ol>';
			errors.innerHTML = str;
			$(errors).removeClassName('off');
		}
	}
	
	function purgeError(f) {
		if(f) {
			var el = document.getElementById('error-' + f);
			if(el) {
				el.parentNode.removeChild(el);
			}
			if(stockErrors[f] !== undefined) {
				nbErrors--;
				if(nbErrors === 0) {
					purgeError();
					return;
				}
				delete stockErrors[f];
			}
			el = null;
		} else {
			$(errors).addClassName('off');
			errors.innerHTML = '';
			nbErrors = 0;
			stockErrors = {};
		}
	}
	
	function destinationIsNotEmpty(submit) {
		var check = ACC.booking.destinationIsNotEmpty(hotelOuVille), f = ACC.fields;
		if(!check) {
			if(f.destination.active && !f.destination.dom.value) {addErrorField('destination');}
			if(f.countries.active && !f.countries.dom.value) {addErrorField('countries');}
			if(f.cities.active && !f.cities.dom.value) {addErrorField('cities');}
			if(f.hotels.active && !f.hotels.dom.value) {addErrorField('hotels');}
			if(!submit) {displayError();}
		} else {
			if(f.destination.active && f.destination.dom.value) {purgeError('destination');}
			if(f.countries.active && f.countries.dom.value) {purgeError('countries');}
			if(f.cities.active && f.cities.dom.value) {purgeError('cities');}
			if(f.hotels.active && f.hotels.dom.value) {purgeError('hotels');}
		}
		f = null;
		return check;
	}
	
	function dateIsNotEmpty(submit) {
		var check = ACC.booking.dateIsNotEmpty();
		if(!check) {
			addErrorField('date');
			if(!submit) {displayError();}
		} else {
			if(!submit) {purgeError('date');}
		}
		return check;
	}
	
	function validate(e) {
		if(e) {
			stockErrors = {};
			nbErrors = 0;
		}
		destinationIsNotEmpty();
		dateIsNotEmpty();
		if(nbErrors > 0) {
			Event.stop(e);
		}
	}
	
	// change hotel/city value in hidden field, do validation
	ACC.fields.destination.addListener('change', function() {
		hotelOuVille.value = this.dom.value;
		purgeError(this.key);
	});
	
	ACC.fields.countries.addListener('change', function() {
		ACC.booking.calendar.setSpecialMaxDepartureDate=false;
		var v = this.dom.value, datas;
		if(this.rawDatas.cities) {
			datas = this.rawDatas.cities[v];
			ACC.fields.cities[datas ? 'update' : 'clear'](datas);
		} else if(this.rawDatas.hotels) {
			datas = this.rawDatas.hotels[v];
			ACC.fields.hotels[datas ? 'update' : 'clear'](datas);
		}
		hotelOuVille.value = '';
		purgeError(this.key);
		/**gestion exception jourMax ibis espagne  -- p1 summer-deals.js**/
		if(ACC.booking.calendar.specialMaxDepartureDate && ACC.booking.calendar.specialMaxDepartureDate.country==v){
			ACC.booking.calendar.maxOri=ACC.booking.calendar.maxDepartureDate;
			ACC.booking.calendar.minOri=ACC.booking.calendar.minDepartureDate;
			ACC.booking.calendar.maxDepartureDate=ACC.booking.calendar.specialMaxDepartureDate.dateMax;
			ACC.booking.calendar.minDepartureDate=ACC.booking.calendar.specialMaxDepartureDate.dateMin;
			ACC.booking.calendar.setSpecialMaxDepartureDate=true;
			var today=new Date();
			ACC.booking.calendar.arrivalDate=ACC.booking.calendar.specialMaxDepartureDate.dateMin<today ? today : ACC.booking.calendar.specialMaxDepartureDate.dateMin;
			ACC.booking.calendar.arrival.value = ACC.booking.calendar.arrivalDate.print(Calendar._TT.DEF_DATE_FORMAT);
			//alert(ACC.booking.calendar.maxDepartureDate+"   "+ACC.booking.calendar.minDepartureDate);
			}
		if(ACC.booking.calendar.specialMaxDepartureDate && ACC.booking.calendar.specialMaxDepartureDate.country!=v){
			ACC.booking.calendar.maxDepartureDate=ACC.booking.calendar.maxOri ? ACC.booking.calendar.maxOri : ACC.booking.calendar.maxDepartureDate;
			ACC.booking.calendar.minDepartureDate=ACC.booking.calendar.minOri ? ACC.booking.calendar.minOri : ACC.booking.calendar.minDepartureDate;
			ACC.booking.calendar.arrivalDate=ACC.booking.calendar.minDepartureDate<today ? today : ACC.booking.calendar.minDepartureDate;
			//alert(ACC.booking.calendar.maxDepartureDate+"   "+ACC.booking.calendar.minDepartureDate);
			ACC.booking.calendar.arrival.value = ACC.booking.calendar.arrivalDate.print(Calendar._TT.DEF_DATE_FORMAT);
		}
		/****/
	});
	
	ACC.fields.cities.addListener('change', function() {
		hotelOuVille.value = this.dom.value;
		purgeError(this.key);
	});
	
	ACC.fields.hotels.addListener('change', function() {
		var v = this.dom.value;
		hotelOuVille.value = v;
		var days = this.rawDatas.specialDays;
		if(days) {
			if(v) {
				var c = 0;
				for(var k in days) {
					c++;
					if(k.indexOf(this.dom.value) > -1) {
						break;
					}
				}
				// if no member defined in specialDays (weekends only)
				if(!c) {
					Calendar.SPECIAL_DAYS = {};
				// if members defined but no match, the loop automatically reach the last key
				// and k == 'Others' (so 'Others' must be in last position)
				} else {
					Calendar.SPECIAL_DAYS = days[k];
				}
			} else {
				Calendar.SPECIAL_DAYS = {};
			}
			ACC.booking.calendar.setMinDate(true);
		}
		purgeError(this.key);
	});
	
	ACC.fields.nights.addListener('fill', changeNights).addListener('change', changeNights).addListener('change', function() {dateIsNotEmpty();});
	ACC.booking.calendar.addListener('change', function() {purgeError('date');});
	
	// reset calendar with special days or not, purge all form errors
	ACC.booking.addListener('change', function() {
		var datas = this.datas[this.current];
		this.calendar.setCalendar(!!datas.specialDays, datas.onlyOneDay);
		purgeError();
	});
	
	// prepare offer choices
	ACC.so = ACC.SpecialOffer({
		context: 'listing-offres',
		items: '#listing-offres div.item',
		cls: {
			item: 'item',
			active: 'on',
			more: 'more',
			book: 'book',
			opened: 'opened',
			close: 'close',
			hide: 'off',
			cgv: 'cgv'
		},
		closeTxt: I18N._('promo.booking.defaults', 'Close'),
		limitHeight: 45,
		activeIndicator: 'active-indicator'
	});
	
	// highlight the correct initial special offer
	ACC.so.desactivate(ACC.so.lastItem);
	ACC.so.activate(promoStart);
	ACC.so.positionArrow($(promoStart));
	ACC.so.lastItem = $(promoStart);
	
	// update booking engine for each offer
	ACC.so.addListener('change', function() {
		if(this.lastItem && this.lastItem.id) {
			hotelOuVille.value = '';
			ACC.fields.destination.dom.value = '';
			ACC.booking.update(this.lastItem.id);
		}
	});
	
	// start the request and add validation
	ACC.booking.getDatas(promoStart);
	ACC.booking.addValidation(validate);
});