/*
Script: qq.js
		Quickquote v2 managed by this script.

License:
        MIT-style license.

About:
		qq.js for mootools framework <http://www.mootools.net/> (c) 2007 Valerio Proietti, MIT-style license.
		Class created by sb, <http://www.floor.ch/>.
		Last modification, 07 january 2008.
		
Version: 1.0

Note:
		XHTML doctype is required.
		
*/

var QuickQuote = new Class({
	Implements : Options,
	
	options: {
		'server' : 'eslagency',
		'junior' : false,
		'ID' : '',
		'CID' : '',
		'lang' : 'fr',
		'year' : 'year',
		'sectionId' : '1',
		'level' : '',
		'course' : '',
		'course2' : '',
		'length' : 0,
		'length2' : 0,
		'date' : '',
		'accom' : '',
		'accomlength' : 0,
		'currency' : '',
		'close_box' : 0,					// Choose the close method 0 for a Slydeout effect / 1 for a simple display:none 
		'ident_contact' : 'qqcontact',
		'ident_print'	: 'qqprint',
		'formID'		: 'qqformular',		
		'hits' : {
			'path' 		: '/cgi/hits_implement.cgi',
			'type'		: 'school'
		},
		'dico' : {
			'combine' 	: 'The length of your first course has been changed to combine with your second course',
			'startdate'	: 'There\'s a problem with the startdate of your second course. Please contact ESL for further information',
			'noresult'	: 'no result'
		}
	},
		
	// called upon creating a class-instance 
	initialize: function(options)	{
		this.setOptions(options);
		
		if (!this.options.sectionId) this.options.sectionId = 1;
		
		//Init qqDictionary
		if (typeof(qqLanguage) != 'undefined') this.options.dico = $merge(this.options.dico, qqLanguage);
		
		this.initBtn();
		if(!this.options.junior) this.initAddCourse();
		this.loader = new Loader();
		this.initYear();
		this.initSchool();
		this.initLevels();
		this.initSupplements('supplements','supplements');
		this.initSupplements('supplnoorder','auxsupplements');
		this.initIncluded('included','included');
	},
	
	// initialize the button to display course 2
	initAddCourse: function(){
		$('addcourse').addEvent('click', function(){
			if($('coursesupp').getStyle('display') != 'block') $('coursesupp').setStyle('display','block');
			else $('coursesupp').setStyle('display','none');
		});
	},
	
	// gets some info about the school
	initSchool: function()	{
		var pars = 'action=getSchoolOfferInfo&item_ID='+this.options.ID+'&CID_school='+this.options.CID;
		
		var success = function(request)	{
			if (!request) 
			return;
			
			var info = request.split('\n');
			$('schoolname').innerHTML = info[0];
			$('schoolNameForm').setProperty('value',info[0]);
			
			$('cityname').innerHTML = info[1];
			$('cityNameForm').setProperty('value',info[1]);
			
			$('countryname').innerHTML = info[2];
			$('countryNameForm').setProperty('value',info[2]);
		}
		
		this._request(pars,success);
	},

	// init the year box if is a published page
	initYear: function()	{
		this._hideCombos(0);
		var pars = 'action=getSchoolOfferYears&item_ID='+this.options.ID;
				
		var success = function(request)	{			
			this._updateCombo(request,'year',0);
			this.loader.load($('year'));
		}.bind(this);
				
		this.loader.load($('year'),'left');
		this._request(pars,success);
	},
	
	// changes the actual year
	changeYear: function(newyear)	{
		this.options.year = newyear;
		this.initLevels();
		this.initSupplements('supplements','supplements');
		this.initSupplements('supplnoorder','auxsupplements');
		this.initIncluded('included','included');
	},
	
	// gets the available levels and fills up the combo 
	initLevels: function()	{
		this._hideCombos(1);
		var pars = 'action=getSchoolOfferLevels&item_ID='+this.options.ID+'&list=level';
		
		var success = function(request)	{
			this._updateCombo(request,'level',1);
			this.loader.load($('level'));
		}.bind(this);
		
		this.loader.load($('level'),'left');
		this._request(pars,success);
	},
	
	// gets the available related-elements according to vars and fills up the combo
	initElements: function(group,combo)	{
		var pars = 'action=getSchoolOfferElements';
		if (group == 'courses')	{
			this._hideCombos(2);
			pars += '&item_ID='+this.options.ID+'&ID_level='+this.options.level;
		}
		else if (group == 'courses2')	{
			this._hideCombos(2);
			pars += '&item_ID='+this.options.ID;
			group = 'courses';
		}
		else	{
			this._hideCombos(5);
			pars += '&item_ID='+this.options.course+'&ElementOption=attach';
		}
		
		pars += '&list=elements&ElementGroup='+group+'&length='+this.options.length;
		
		var success = function(request)	{
			this._updateCombo(request,combo,1);
			if(combo == 'course2'){
				if($('coursesupp').getStyle('display')=='block') this.loader.load($(combo),'left');
			}else this.loader.load($(combo),'left');
		}.bind(this);
		
		if(combo == 'course2'){
			if($('coursesupp').getStyle('display')=='block') this.loader.load($(combo),'left');
		}else this.loader.load($(combo),'left');
		
		this._request(pars,success);
	},
	
	// gets the supplements for the given element (school)
	initSupplements: function(list,el)	{
		var pars = 'action=getSchoolOfferElements&item_ID='+this.options.ID+'&list='+list+'&ElementGroup=supplements';
		this._request(pars,'',$(el));
	},
	
	// gets the included for the given element (school)
	initIncluded: function(list,el)	{
		var pars = 'action=getSchoolOfferElements&item_ID='+this.options.ID+'&list='+list+'&ElementGroup=included';
		this._request(pars,'',$(el));
	},
	
	// gets the lengths possible for this course
	initLengths: function(combo,option)	{
		var pars = 'action=getSchoolOfferLengths&list=length';
		
		this.loader.load($(combo),'left');
		
		if (option == 'second')	{
			$(combo).disabled = true;
			$(combo).length = 1;
			this.options[combo] = ''
			pars += '&item_ID='+this.options.course2;
		}
		else	{
			this._hideCombos(3);
			pars += '&item_ID='+this.options.course;
		}
		
		var success = function(request)	{
			this._updateCombo(request,combo,1);
			this.loader.load($(combo),'left');
		}.bind(this);
		
		this._request(pars,success);
	},
	
	// gets the lengths possible for this accommodation
	initAccomLengths: function(lbl)	{
		$('accomlength').disabled = true;
		var courselength = parseInt(this.options.length);
		if (parseInt(this.options.length2))
			courselength += parseInt(this.options.length2);
		if (!courselength)
			courselength = 1;
		
		if ($('length').options[$('length').selectedIndex].text.match(/\+.*?/))	{
			var extralength = parseInt($('length').options[$('length').selectedIndex].text.replace(/.*?\+/,''));
			if (extralength)
				courselength += extralength;
		}
		if ($('length2') && $('length2').options[$('length2').selectedIndex].text.match(/\+.*?/))	{
			var extralength = parseInt($('length2').options[$('length2').selectedIndex].text.replace(/.*?\+/,''));
			if (extralength)
				courselength += extralength;
		}
		
		var accomlengths = '';
		var initc = 2;
		if (courselength == 1)	initc = 1;
		for (var c=initc; c<=courselength; c++)	{
			accomlengths += c+'::'+c+' '+lbl+'\n';
		}
		this._updateCombo(accomlengths,'accomlength',1);
	},
	
	// gets the available startdates
	initDates: function()	{
		this._hideCombos(4);
		var pars = 'action=getSchoolOfferDates&item_ID='+this.options.ID+'&ID_course='+this.options.course+'&ID_level='+this.options.level+'&length='+this.options.length+'&list=date';
		
		var success = function(request)	{
			this._updateDates(request,'startdate');
			this.loader.load($('startdate'),'left');
		}.bind(this);
		
		this.loader.load($('startdate'),'left');
		this._request(pars,success);
	},
	
	// controls the startdate for the second course
	checkStartdateForCourse2: function()	{
		if (!this.options.length || !this.options.length2 || !this.options.date)
			return;
		
		var pars = 'action=checkSchoolOfferStartdate&item_ID='+this.options.ID+'&ID_course='+this.options.course2+'&length='+this.options.length+'&length2='+this.options.length2+'&startdate='+this.options.date+'&list=date';
		
		var success = function(request)	{
			if (!request) 
                                return;
			var result = request.split('/');
			var newselect = false;
			if (result[0] != '1' && result[1] != '0')	{
				for (var c=0; c<$('length').length; c++)	{
					if ($('length').options[c].value == result[1])	{
						$('length').options[c].selected = true;
						this.options.length = result[1];
						newselect = true;
						this._showMessage(this.options.dico.combine);
						break;
					}
				}
			}
			if (newselect == false && result[0] != '1')	{
				this._showMessage(this.options.dico.startdate);
			}
		}.bind(this);
		
		this._request(pars,success);
	},	
	
	// calculates the price for the given choice
	calculate: function()	{
		
		this.incrHits({ 'label': 'QQhits', 'sendform': '0' });
		
		$('price').setStyle('display','block');
		var suppls = this._getCBValues('supplements');
		var pars = 'action=getSchoolOfferPrice&item_ID='+this.options.ID+'&ID_course='+this.options.course+'&ID_course2='+this.options.course2+'&ID_accom='+this.options.accom+'&list=result&length='+this.options.length+'&length2='+this.options.length2+'&accomlength='+this.options.accomlength+'&startdate='+this.options.date+'&currency='+this.options.currency+'&id_section='+this.options.sectionId+'&IDs_suppl='+suppls;
		$('blockbtn').setStyle('display','block');
		$('blockbtn').getElements('input').each(function(el){
			el.setStyle('visibility','visible').addEvent('click', 
				function(e) {
					new Event(e).stop();	
				}); 		
		});

		this._request(pars,'',$('offerprice'));
	},
	
	// ------------------------------------------------------------------
	// Private functions
	
	// does all ajax-requests 
	_request: function(pars,success,update)	{
		var server = this.options.server;
		pars = 'server='+server+'&lang='+this.options.lang+'&'+pars+'&UsedYear='+this.options.year+'&datatype=school&ID_section='+this.options.sectionId+'&ajaxrequest=1&randomnumber='+Math.random();

		var options = {
			url : window.location.protocol + "//" + window.location.hostname + window.location.pathname,
			method: 'post',
			data: pars, 
			// Handle other errors
			onFailure: function(request) {
				alert('Error -- ' + request);
			}
		}
		
		if (success != '') {
			options['onSuccess'] = function(request) { success(request); };
		} else if (update)	{
			$(update).innerHTML = '';
			this.loader.load($(update));
			//options['update'] = update;
			options['onSuccess'] = function(request) { 
				// Check if the request is empty and hide the box
				if (!request) {
					$(update).innerHTML = "<span class='qqlabel'>"+this.options.dico.empty+"</span>";
				} else {
					$(update).innerHTML = request;
				}
				
				this.loader.load($(update));
				
				//add some style and fashion ; )
				if(update.id == 'supplements' || update.id == 'auxsupplements') this.customize(update.id);
			}.bind(this)
		}
		
		var myAjax = new Request(options).send();
	},
	
	// updates a combo with the given values
	_updateCombo: function(request,combo,combo_length)	{
		if (!$(combo))
			return;
		
		$(combo).length = combo_length;

		if (!request) {
			if ($(combo).getParent().getElements('em').length <= 0) {
				new Element('em').set('text', this.options.dico.noresult).injectAfter($(combo));
			}
			return;
		}
		var res = request.split('\n');
		var c;
		for (c=0; c<res.length; c++)	{
			if (res[c] == '') continue;
			var pair = res[c].split('::');
			$(combo).options[$(combo).length] = new Option(pair[1], pair[0], false, false);

			if (combo == 'year' && pair[0] == this.options.year) {				
				$(combo).options[$(combo).length -1].selected = 'selected'; // for IE
				//$(combo).options[$(combo).length -1].setProperty('selected','selected');
			}
		}
		
		if ($('coursesinfo').getElements('em').length > 0 && combo !='length2') {
			$('coursesinfo').getElements('em').each(function(msg){
				msg.destroy();
			});
		}
		
		$(combo).disabled = false;
	},
	
	// hides the combos according to the step
	_hideCombos: function(step)	{
		var combos = this.options.junior ? new Array('year','level','course','length','startdate','accom') : new Array('year','level','course,course2','length','startdate','accom','accomlength');
		
		for (var c=step; c<combos.length; c++)	{
			var coms = combos[c].split(',');
			for (var i=0; i<coms.length; i++)	{
				$(coms[i]).disabled = true;
				$(coms[i]).length = 1;
				if (step != 0)
					this.options[coms[i]] = '';
			}
		}
		
		if (!this.options.junior && (step == 0 || step == 1 || step == 2))	{
			$('length2').disabled = true;
			$('length2').length = 1;
			this.options.length2 = '';
		}
		if (step <= 4)
			$('docalc').disabled = true;
	},
	
	// splits up the datestring according to levels and lengths and feeds then updateCombo with 
	// the correct values
	_updateDates: function(request,combo)	{
		var result = this._getWorkingDatestr(request,this.options.level,this.options.length);
		this._updateCombo(result,combo,1);
	},
	
	// splits up the datestring into an array
	_getWorkingDatestr: function(datestr,level,length)	{
		var result = new Array(new Array, new Array);
		if (!datestr)
			return '';
		var res = datestr.split('\n');
		for (var c=0; c<res.length; c++)	{
			if (res[c] == '') continue;
			var vals = res[c].split('::');
			if (vals[0] == '') vals[0] = 0;
			if (vals[1] == '') vals[1] = 0;
			if (!result[vals[0]]) result[vals[0]] = new Array;
			if (!result[vals[0]][vals[1]]) result[vals[0]][vals[1]] = '';
			result[vals[0]][vals[1]] += vals[2]+'::'+vals[3]+'\n';
		}
		if (result[level] && result[level][length])
			return result[level][length];
		else if (result[level] && result[level][0])
			return result[level][0];
		else if (result[0][length])
			return result[0][length];
		else
			return result[0][0];
	},
	
	// gets the values of the checked checkboxes inside the given element
	_getCBValues: function(el)	{
		var idstr = '';
		var suppls = $(el).getElementsByTagName('input');
		
		for(var c=0; c<suppls.length; c++)	{
			if (suppls[c].type == 'checkbox' && suppls[c].checked == true)	{
				if (idstr)	idstr += ',';
				idstr += suppls[c].value;
			}
		}
		return idstr;
	},
	
	_showMessage: function(msg)	{
		$('infomsg').innerHTML = msg;
	},
	
	initBtn : function() {
		$('btncontact').addEvent('click', function() { 
			this.pushQQResult();						
			$('category_ident').setProperty('value', this.options.ident_contact);
			$(this.options.formID).setProperty('target','');
			this.incrHits({ 'label': 'QQcontacthits', 'sendform': '1' });
		}.bind(this)); 
		
		$('btnprint').addEvent('click', function() { 
			this.pushQQResult();
			$('category_ident').setProperty('value', this.options.ident_print);
			this.incrHits({ 'label': 'QQprinthits', 'sendform': '0' });
			$(this.options.formID).setProperty('target','_blank').submit();	
		}.bind(this)); 
	},
	
	incrHits : function(data) {		
		if (this.options.IID == '') { return ''; }
		var name = $('schoolname').innerHTML +' - '+ $('cityname').innerHTML;
		var param = 'lang='+this.options.lang+"&iID="+this.options.ID+"&schoolyear="+this.options.year+"&name="+name+"&type="+this.options.hits.type+'&label='+data.label;
		var myRequest = new Request({
			url: window.location.protocol + "//" + window.location.hostname + this.options.hits.path,
			method: 'post',
			data : param, 
			onComplete: function() {
				if (data.sendform == '1') {
					$(this.options.formID).submit();	
				}
			}.bind(this)
		}).send();
	},
	
	pushQQResult : function() {
		// put qq value into hidden field (use for qqcontact & qqprint)
		$('levelName').setProperty('value',$('level').options[$('level').selectedIndex].innerHTML);
		$('divprice').setProperty('value',$('offerprice').innerHTML.replace(/"/g,"'"));
		$('divincluded').setProperty('value',$('included').innerHTML.replace(/"/g,"'"));
		$('divsuppl').setProperty('value',$('auxsupplements').innerHTML.replace(/"/g,"'"));
	},
	
	customize : function(id){
		//add even class on some lines
		$(id).getChildren().each(function(row, i){
			if (i%2 == 1) row.addClass('even');
		});
		
	}
		
});

// --------------------------------------------------------------
// object for calculations on dates
if (!FloorDateCalc)	{
	var FloorDateCalc = {
		// Non-Leap year Month days..
		DaysInMonth : new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
		// Leap year Month days..
		LDaysInMonth : new Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
		// --------------------------------------------------------------
		// compares 2 dates: returns -1 if date2 is before, 0 if they're
		// equal, 1 if date2 is after, nothing if one date is invalid format
		compare : function(date1,date2)	{
			if (!date1.match(/\d+?-\d+?-\d+/) || !date2.match(/\d+?-\d+?-\d+/))	{
				return;
			}

			var d1 = this.splitDate(date1);
			var d2 = this.splitDate(date2);
			
			// first check year
			if (d1[0] > d2[0])	{
				return -1;
			}
			else if (d1[0] < d2[0])	{
				return 1;
			}
			// we're in the same year so check month next
			else if (d1[1] > d2[1])	{
				return -1;
			}
			else if (d1[1] < d2[1])	{
				return 1;
			}
			// same month and year, so compare days
			else if (d1[2] > d2[2])	{
				return -1;
			}
			else if (d1[2] < d2[2])	{
				return 1;
			}
			// if we arrive here, the 2 dates are identical
			else	{
				return 0;
			}
		},
		
		// --------------------------------------------------------------
		// adds the given amount of days to a date
		// returns the new date
		addRemoveDays : function(date,days)	{
			var wdate = this.splitDate(date);
			
			var daysadded = 0;
			
			while (daysadded < days)	{
				var dim = this.getDaysInMonth(wdate);
				var add = dim - wdate[2];
				if (add > days - daysadded)
					add = days - daysadded;
				
				wdate[2] += add;
				daysadded += add;
				
				if (wdate[2] == dim && days != daysadded)	{
					if (wdate[1] == 12)	{
						wdate[0]++;
						wdate[1] = 1;
					}
					else
						wdate[1]++;
					wdate[2] = 1;
					daysadded++;
				}
			}
			
			return wdate[0]+'-'+wdate[1]+'-'+wdate[2];
		},
		
		// --------------------------------------------------------------
		// gets the difference in days between 2 dates
		// returns the difference
		getDiffDays : function(date1,date2)	{
			var wdate1 = new Array();
			var wdate2 = new Array();
			var compare = this.compare(date1,date2);
			
			if (compare == -1)	{
				wdate1 = this.splitDate(date2);
				wdate2 = this.splitDate(date1);
			}
			else if (compare == 1)	{
				wdate1 = this.splitDate(date1);
				wdate2 = this.splitDate(date2);
			}
			else	{
				return 0;
			}
			
			var daysadded = 0;
			
			while (this.compare(wdate1[0]+'-'+wdate1[1]+'-'+wdate1[2],wdate2[0]+'-'+wdate2[1]+'-'+wdate2[2]) == 1)	{
				var dim = this.getDaysInMonth(wdate1);
				var add = dim - wdate1[2];
				if (wdate1[0] == wdate2[0] && wdate1[1] == wdate2[1])
					add = wdate2[2] - wdate1[2]; 
				
				wdate1[2] += add;
				daysadded += add;
				
				if (wdate1[2] == dim && this.compare(wdate1[0]+'-'+wdate1[1]+'-'+wdate1[2],wdate2[0]+'-'+wdate2[1]+'-'+wdate2[2]) == 1)	{
					if (wdate1[1] == 12)	{
						wdate1[0]++;
						wdate1[1] = 1;
					}
					else
						wdate1[1]++;
					wdate1[2] = 1;
					daysadded++;
				}
			}
			return daysadded;
		},
		
		// --------------------------------------------------------------
		// checks if it's a valid date
		// returns 0 for invalid, 1 for valid
		check : function(date)	{
			if (!date)	{
				return 0;
			}
			if (!date.match(/\d+?-\d+?-\d+/))	{
				return 0;
			}
			var d = this.splitDate(date);
			// check month 
			if (d[1] > 12 || d[1] < 1)	{
				return 0;
			}
			// check day
			if (d[2] < 1 || d[2] > this.getDaysInMonth(d))	{
				return 0;
			}
			return 1;
		},
		
		// --------------------------------------------------------------
		// splits a date into year, month and day and convert to integer
		// returns an array
		splitDate : function(datestr)	{
			var date = datestr.split('-');
			date = this.convert(date);
			return date;
		},
		
		// --------------------------------------------------------------
		// converts a datearray to integer or string (default is integer) 
		// returns an array
		convert : function(date,mode)	{
			var c;
			for (c=0; c<date.length; c++)	{
				switch (mode)	{
					case "string":
						date[c] = date[c].toString();
					break;
					case "fullstring":
						date[c] = (date[c].length == 1) ? date[c] = '0'+date[c].toString() : date[c] = date[c].toString();
					break;
					default:
						date[c] = (date[c].length == 2 && date[c].substr(0,1) == '0') ? parseInt(date[c].substr(1,1)) : parseInt(date[c]);
					break;
				}
			}
			return date;
		},
		
		// --------------------------------------------------------------
		// gets the amount of days in a month according to leapyear-rules 
		// returns the amount of days
		getDaysInMonth : function(Date)	{
			if ((Date[0] % 4) == 0) {
				if ((Date[0] % 100) == 0 && (Date[0] % 400) != 0)	{
					return this.DaysInMonth[Date[1]-1];
				}
				else	{
					return this.LDaysInMonth[Date[1]-1];
				}
			}
			else	{
				return this.DaysInMonth[Date[1]-1];
			}
		}
	}
}

