// Postulats :
// 1)	Les objets ne construisent pas de contenu HTML (celui-ci est un attribut de listItem)
// 2)	Les objets ne gèrent pas le style d'affichage de la liste
// -------------------------------------------------------------------------------------------------------------------------------
// Surcharge de l'objet Array
// -------------------------------------------------------------------------------------------------------------------------------
Array.prototype.clone = function(){
	return Array.apply(null,this)
};
Array.prototype.sortIt    = Array.prototype.sort;
Array.prototype.reverseIt = Array.prototype.reverse;
// Redéfinition des méthodes sort et reverse de l'objet Array
// => Le tableau est retourné trié mais demeure en mémoire dans son état initial
Array.prototype.sort = function(){
	var tmp = this.clone();
	return tmp.sortIt.apply(tmp,arguments)
}
Array.prototype.reverse = function(){
	var tmp = this.clone();
	return tmp.reverseIt.apply(tmp,arguments)
}
// -------------------------------------------------------------------------------------------------------------------------------
// Classe listItem
// -------------------------------------------------------------------------------------------------------------------------------
function listItem (sf, ff, co) {
	// attributs
	this.filterField = ff;
	this.sortField = sf;
	this.content = co;
	
	// méthodes
	this.setContent = function (co) {
		this.content = co;
	}
	this.setFilterField = function (ff) {
		this.filterField = ff;
	}
	this.setSortField = function (sf) {
		this.sortField = sf;
	}
	this.getSortField = function () {
		return (this.sortField);
	}
	this.getFilterField = function () {
		return (this.filterField);
	}
	this.getContent = function () {
		return (this.content);
	}
}
// -------------------------------------------------------------------------------------------------------------------------------
// Classe listContener
// -------------------------------------------------------------------------------------------------------------------------------
function listContener (lcid, pcids, mitd) {
	// attributs
	// --------------------------------------------------------------------------------------------------------
	this.maxItemsToDisplay = mitd;			// nb max d'éléments affichés par page
	this.listContenerId = lcid;				// Id du contener (au sens Dom)  associé à la liste 
	this.pagerContenerIds = pcids;			// Tableau d'ids des contener (au sens Dom)  associé à la pagination 
	this.listItems = new Array ();			// liste initiale (utile pour le reset)
	this.listItemsToDisplay = new Array ();	// liste utilisée pour l'affichage
	this.isSort = false;					// état de la liste [tri]
	this.isReverse = false;					// état de la liste [tri inverse]
	this.isFilter = false;					// état de la liste [filtre actif]
	this.currentFilter = "";				// Filtre en cours
	this.currentPagerPage = 0;					// n° de Page du pager courante
	
	// methodes
	// --------------------------------------------------------------------------------------------------------
	// addItem : ajout d'un nouvel élément dans la liste
	// ff		-> critère utilisé pour filtrer la liste
	// co		-> contenu HTML d'un élément de la liste
	this.addItem = function addItem (sf,ff,co) {
		this.listItems[this.listItems.length] = new listItem (sf,ff,co);
		this.listItemsToDisplay[this.listItemsToDisplay.length] = new listItem (sf,ff,co);
	}
	// dump : affichage de l'objet (dev et debug  only)
	this.dump = function () {
		var dumpContent = "Stored list :\n";
		for (var i=0; i < this.listItems.length; i++)
			dumpContent += "Sort["+this.listItems[i].getSortField()+"] - Filter["+this.listItems[i].getFilterField()+"] - Content["+this.listItems[i].getContent()+"]\n";
	
		dumpContent+="Displayed list :\n";
		for (var i=0; i < this.listItemsToDisplay.length; i++)
			dumpContent += "Sort["+this.listItemsToDisplay[i].getSortField()+"] - Filter["+this.listItemsToDisplay[i].getFilterField()+"] - Content["+this.listItemsToDisplay[i].getContent()+"]\n";
	
		alert (dumpContent);
	}
	// draw : affichage de la liste dans le contener prévu à cet effet
	// lid		-> id du contener associé à la liste dans le document
	// from	-> variable qui indique le point de départ d'affichage de la liste
	this.draw = function (from) {
		var domContener = document.getElementById(this.listContenerId);
		var to = from + this.maxItemsToDisplay;
	
		if ( to > this.listItemsToDisplay.length )
			to = this.listItemsToDisplay.length;
		
		var htmlContent = "";
	
		for ( var i=from; i < to; i++ )
			htmlContent += this.listItemsToDisplay[i].getContent();
		
		domContener.innerHTML = htmlContent;
	}
	// getCurrentPagerPage : renvoit la page courante du pager
	this.getCurrentPagerPage = function () {
		return (this.currentPagerPage);
	}
	// updatePager : affichage de la pagination asociée à la liste
	// oList	-> nom de l'objet associé à la liste (utilisé pour créer les liens pendant la pagination)
	this.updatePager = function (oList, idx) {
		var nbPages = this.listItemsToDisplay.length / this.maxItemsToDisplay;
		var htmlContent = "";
		
		// Création des numéros de page et des liens associés
		for ( var i=0 ; i < nbPages; i++ ) {
			if ( i != idx )
				htmlContent += "<a href=\"javascript:"+oList+".draw("+i*this.maxItemsToDisplay+"); "+oList+".updatePager('"+oList+"', "+i+");\">"+(i+1)+"</a>"
			else
				htmlContent += (i+1)
			htmlContent += "&nbsp;&nbsp;&nbsp;&nbsp;"
		}
		// Mise à jour de la page courante
		this.currentPagerPage = idx;
		// Mise à jour des container de pagination
		for (var i=0; i<this.pagerContenerIds.length; i++)
			document.getElementById(this.pagerContenerIds[i]).innerHTML = htmlContent;
	}
	// comparePrice : méthode de comparaison de base pour effectuer le tri	
	this.comparePrice = function ( objectA, objectB ) {
		return ( objectA.getSortField() - objectB.getSortField() );
	}
	// sortByPrice : méthode de tri sur le prix
	this.sortByPrice = function () {
		this.listItemsToDisplay.sortIt (this.comparePrice);

		this.isSort = true;
		this.isReverse = false;
		// En cas de tri on repart de 0
		this.draw (0);
	}
	// reverse : inversion du tableau d'affichage (si la liste est déjà triée au départ cela permet d'avoir un effet croissant ou décroissant)
	this.reverse = function () {
		this.sortByPrice();
		this.listItemsToDisplay.reverseIt();
		this.isReverse = true;
		
		// En cas d'inversion on repart de 0
		this.draw (0);
	}

	// filter : filtrage du tableau d'affichage
	// flt		-> paramètre de filtrage
	this.filter = function (flt) {
		delete this.listItemsToDisplay;
		this.listItemsToDisplay = new Array();
		
		for (var i=0; i < this.listItems.length; i++) {
			if ( this.listItems[i].getFilterField() == flt )
				this.listItemsToDisplay[this.listItemsToDisplay.length] = new listItem (this.listItems[i].getSortField(), flt,this.listItems[i].getContent());
		}
		// On restaure le tri choisi avant filtrage
		if (this.isSort == true ) {
			if (this.isReverse == true ) {
				this.sortByPrice();
				this.reverse();
			}
			else {
				this.sortByPrice();
			}
		}
		
		this.isFilter = true;
		this.currentFilter = flt;
		// En cas de filtrage on repart de 0 ( page 1)
		this.draw (0);
	}
	// reset : réinitialisation de la liste
	this.reset = function () {
		delete this.listItemsToDisplay;
		this.listItemsToDisplay = new Array();
		
		for (var i=0; i < this.listItems.length; i++) {
			this.listItemsToDisplay[this.listItemsToDisplay.length] = new listItem (this.listItems[i].getSortField(), this.listItems[i].getFilterField(),this.listItems[i].getContent());
		}

		this.isSort = false;
		this.isReverse = false;
		this.isFilter = false;
		this.currentFilter = "";

		this.draw (0);
	}
	this.resetPrice = function () {
		var flt = "";
		
		if ( this.isFilter == true ) {
			flt = this.currentFilter;
			this.reset ();
			this.filter (flt);
		}
		else
			this.reset ();
	}
	this.resetFilter = function () {
		if (this.isSort == true ) {
			if (this.isReverse == true ) {
				this.reset();
				this.sortByPrice();
				this.reverse();
			}
			else {
				this.reset();
				this.sortByPrice();
			}
		}
		else
			this.reset();
	}
}