/**
 * Class: Calendrier
 *  v 0.2 
 *   
 * =============================
 *  GROUP: Constantes
 * ============================= 
 * 
 * Var VERSION
 *  Version du Calendrier   
 */ 
Calendrier.VERSION = "0.2"; 
/**
 * Var: _INSTANCE
 *  Numero du calendrier en cours
 */ 
Calendrier._INSTANCE = 0;
/**
 * Var: aMoisFr
 *  Les mois en Francais
 */  
Date.aMoisFr = [
	'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 
	'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'
];
/**
 * Var: aJoursFeries
 *  Les jours feries Francais
 */  
Date.aJoursFeries = [
	'01/01', '01/05', '08/05', '14/07', '15/08', '01/11', 
	'11/11', '25/12'
];
/**
 * ==================================
 * GROUP: Tools pour le Calendrier
 * ==================================
 * 
 * Method: renvoieJoursDansMois
 *  
 * Returns:
 *  Int le nombre de jour dans le mois (pour un objet de type date)
 */  
Date.prototype.renvoieJoursDansMois = function () {
	var dDateTmp = new Date(this.getFullYear(), this.getMonth(), 1);
	var nJours = 0;
	for (var i = 27; i <= 32; i++) {
		dDateTmp.setDate(i);
		if (dDateTmp.getMonth() != this.getMonth()) {
			nJours = i - 1;
			break;
		}
	}
	return nJours;
};
/**
 * Method: estFerie
 * 
 * Returns:   
 *  Boolean true si ferie (pour un objet de type date) 
 */ 
Date.prototype.estFerie = function (j, m) {
	for (var i = 0; i < Date.aJoursFeries.length; i++) {
		if (Date.aJoursFeries[i].substring(0, 2) == j && Date.aJoursFeries[i].substring(3, 5) == m)
			return true;
	}
	return false;
};
/**
 * Method: renvoiePremierJourDuMois
 * 
 * Returns:   
 *  Int premier jour du mois (pour un objet de type date) 
 */ 
Date.prototype.renvoiePremierJourDuMois = function () { // (ou 0 est dimanche)
	var dDateTmp = new Date(this.getFullYear(), this.getMonth(), 1);
	return (dDateTmp.getDay() == 0) ? 7 : dDateTmp.getDay();
};
/**
 * Method: combleDate
 * 
 * Returns:   
 *  String sur deux caracteres (pour un type nombre) 
 */ 
Number.prototype.combleDate = function () {
	return (this < 10) ? "0"+this : this;
};
/**
 * ==================================
 * Class: Calendrier
 * ==================================
 *  
 * Constructor: Calendrier 
 *  
 */ 
function Calendrier(oAction, oDate, oRestrictions) {
	this._nINSTANCE = ++Calendrier._INSTANCE;
	this._initialise(oAction, oDate, oRestrictions);
};
/**
 * Method: _initialise
 *  Init. du calendrier, a invoquer aussi avant une mise a jour de l'affichage
 *  Dans la fonction de callback, le parametre oEvent contient une representation 
 *  de l'objet date {annee:aaaa, mois:mm, jour:jj } et l'objet cible target  
 *  
 * Parameters:   
 *  oAction: Objet contenant Object scope et String callback
 *  oDate: Object contenant Number annee, Number mois (1 a 12), Number jour
 *  oRestrictions 
 */  
Calendrier.prototype._initialise = function(oAction, oDate, oRestrictions) {
	this._oAction 			= oAction;
	this._oDate 			= oDate;
	this._oRestrictions 	= oRestrictions;
	this._dDate 			= new Date(oDate.annee, oDate.mois-1, oDate.jour);
	this._nJours 			= this._dDate.renvoieJoursDansMois();
	this._nPremierJour 		= this._dDate.renvoiePremierJourDuMois();
	this._sCalque 			= null;
	this._sNomCalque 		= "";
	this._sHtml 			= "";
};
/**
 * Method: affiche
 *  Affichage du calendrier
 *  
 * Parameters:
 *  sNomCalque, String le nom du calque de destination   
 */ 
Calendrier.prototype.affiche = function(sNomCalque) {
	var _THIS_ = this;
	var aJours = [];
	var i = 0, j = 0, k = 0, l = 0, nMoisMin = 0, nMoisMax = 0, nAnneeMin = 0, nAnneeMax = 0;
	var bCliquable;
	if (this._oRestrictions.INTERDITS == undefined) { this._oRestrictions.INTERDITS = []; }
	// Borne des annees
	nAnneeMin = (this._oRestrictions.MIN.annee != undefined) ? this._oRestrictions.MIN.annee : new Date().getFullYear();
	nAnneeMax = (this._oRestrictions.MAX.annee != undefined) ? this._oRestrictions.MAX.annee : new Date().getFullYear() + 100;
	if (nAnneeMin > nAnneeMax) {
		nAnneeMin = new Date().getFullYear();
		nAnneeMax = new Date().getFullYear() + 100;
	}
	// Borne des mois
	nMoisMin = (this._oRestrictions.MIN.mois != undefined && this._dDate.getFullYear() == this._oRestrictions.MIN.annee) ? this._oRestrictions.MIN.mois-1 : 0;
	nMoisMax = (this._oRestrictions.MAX.mois != undefined && this._dDate.getFullYear() == this._oRestrictions.MAX.annee) ? this._oRestrictions.MAX.mois : Date.aMoisFr.length;
	if (nMoisMin > nMoisMax) {
		nMoisMin = 0;
		nMoisMax = Date.aMoisFr.length;
	}
	// !!!!!!!!  Cas particuliers  !!!!!!!!
	if (nMoisMin == this._oRestrictions.MIN.mois-1 && nMoisMin > this._dDate.getMonth()) {
		this._initialise(this._oAction, {annee:this._dDate.getFullYear(), mois:this._oRestrictions.MIN.mois, jour:1}, this._oRestrictions);
		this.affiche(sNomCalque);
	}
	if (nMoisMax == this._oRestrictions.MAX.mois && this._dDate.getMonth() > nMoisMax-1) {
		this._initialise(this._oAction, {annee:this._dDate.getFullYear(), mois:this._oRestrictions.MAX.mois, jour:1}, this._oRestrictions);
		this.affiche(sNomCalque);
	}
	//
	// Borne des jours
	if (this._oRestrictions.MIN.annee == this._dDate.getFullYear() && this._oRestrictions.MIN.mois-1 == this._dDate.getMonth() && this._oRestrictions.MIN.jour != undefined) {
		for (i = 1; i <= this._oRestrictions.MIN.jour; i++) {
			this._oRestrictions.INTERDITS.push({annee:this._dDate.getFullYear(), mois:this._dDate.getMonth(), jour:i});	
		}
	}
	if (this._oRestrictions.MAX.annee == this._dDate.getFullYear() && this._oRestrictions.MAX.mois-1 == this._dDate.getMonth() && this._oRestrictions.MAX.jour != undefined) {
		for (i = this._oRestrictions.MAX.jour+1; i <= this._nJours; i++) {
			this._oRestrictions.INTERDITS.push({annee:this._dDate.getFullYear(), mois:this._dDate.getMonth(), jour:i});
		}
	}
	//
	var nJours7 = this._nJours + this._nPremierJour - 1;
	while (nJours7%7 != 0 && nJours7 <= 50) nJours7++;
	this._sNomCalque = sNomCalque;
	this._sCalque = $(this._sNomCalque);
	this._sCalque.update("");
	this._sHtml = "";
	this._sHtml += "<table class=\"calendrierTableau\">\n"; 
	this._sHtml += "	<tr>\n";
	this._sHtml += "		<td colspan=\"7\" class=\"calendrierLigneFormulaire\">\n";
	this._sHtml += "			<select id=\"selectMois"+this._nINSTANCE+"\">\n";
	for (i = nMoisMin; i < nMoisMax; i++) {
		this._sHtml += "				<option value=\""+i+"\""+((this._dDate.getMonth() == i) ? " selected=\"selected\"" : "")+">"+Date.aMoisFr[i].substr(0, 3)+"</option>";
	}
	this._sHtml += "			</select>&nbsp;\n";
	this._sHtml += "			<select id=\"selectAnnee"+this._nINSTANCE+"\">\n";
	for (i = nAnneeMin; i <= nAnneeMax; i++) {
		this._sHtml += "				<option value=\""+i+"\""+((this._dDate.getFullYear() == i) ? " selected=\"selected\"" : "")+">"+i+"</option>";
	}
	this._sHtml += "			</select>&nbsp;\n";
	this._sHtml += "		</td>\n";
	this._sHtml += "	</tr>\n";
	this._sHtml += "	<tr>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Lu</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Ma</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Me</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Je</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Ve</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Sa</td>\n";
	this._sHtml += "		<td class=\"calendrierEnteteJour\">Di</td>\n";
	this._sHtml += "	</tr>\n";
	for (var i = 1; i <= nJours7; i++) {
		if (i == 1 || (i-1) % 7 == 0) this._sHtml += "	<tr>\n";
		if(i >= this._nPremierJour && j < this._nJours) {
			k = ++j;
			this._sHtml += "		<td class=\"calendrierColonneJour\">\n"; 
			bCliquable = true;
			for (l = 0; l < this._oRestrictions.INTERDITS.length; l++) {
				if (this._oRestrictions.INTERDITS[l].annee == this._dDate.getFullYear() && this._oRestrictions.INTERDITS[l].mois == this._dDate.getMonth() && this._oRestrictions.INTERDITS[l].jour == k) {
					bCliquable = false;
					break;	
				}
			}
			if (bCliquable) {
				this._sHtml += "			<p><a class=\"calendrierLien\" id=\"jour_"+this._nINSTANCE+"_"+i+"\" href=\"javascript:void(0);\">"+k.combleDate()+"</a></p>";
				aJours.push({
					id:'jour_'+this._nINSTANCE+'_'+i, 
					oDate:{annee:this._oDate.annee, mois:this._oDate.mois.combleDate(), jour:k.combleDate()}
				});	
			} else {
				this._sHtml += "			<p class=\"jourInterdit\">"+k.combleDate()+"</p>";
			}
			this._sHtml += "		</td>\n";
			
		} else {
			this._sHtml += "		<td class=\"calendrierColonneJour\">&nbsp;</td>\n";
		}
		if (i % 7 == 0 || i == nJours7) 
			this._sHtml += "	</tr>\n";
	}
	this._sHtml += "</table>\n";
	this._sCalque.update(this._sHtml);
	for (i = 0; i < aJours.length; i++) {
		$(aJours[i].id).i = i;
		$(aJours[i].id).onclick = function() {
			var oArguments = aJours[this.i].oDate;
			oArguments.target = _THIS_;
			_THIS_._oAction.scope[_THIS_._oAction.callback](oArguments);
		};
	}
	$('selectMois'+this._nINSTANCE).onchange = function() {
		var sNomCalque = _THIS_._sNomCalque;
		var oDate = {annee:_THIS_._oDate.annee, mois:Number(this.value)+1, jour:1};
		_THIS_._initialise.apply(_THIS_, [_THIS_._oAction, oDate, _THIS_._oRestrictions]);
		_THIS_.affiche.apply(_THIS_, [sNomCalque]);
	};
	$('selectAnnee'+this._nINSTANCE).onchange = function() {
		var sNomCalque = _THIS_._sNomCalque;
		var oDate = {annee:this.value, mois:_THIS_._oDate.mois, jour:1};
		_THIS_._initialise.apply(_THIS_, [_THIS_._oAction, oDate, _THIS_._oRestrictions]);
		_THIS_.affiche.apply(_THIS_, [sNomCalque]);
	};	
};
/**
 * ==================================
 * GROUP: Specialisation du calendrier
 * ==================================
 *  
 * Method: Calendrier 
 *  A appeler a partir de l'evenement oEvent.target
 */
Calendrier.prototype.ferme = function() {
	this._sCalque.hide();
};
/**
 * Method: toggle
 *  Meme fonctionnement que toggle de prototype (afficher/masquer n fois)
 */  
Calendrier.prototype.toggle = function(sCalque) {
	this.affiche(sCalque);
	$(sCalque).toggle();
}

