/** 
 * L'objet en argument doit contenir deux valeurs:
 * token: le token de session
 * objName: le nom du type d'objet voulu (sa classe)
 * 
**/
function t41Query(o) {
	
	this.token = (o.token==null)? null: o.token;
	this.objName = (o.objName==null)? null: o.objName;
	this.func = "query";
	this.queries = []; // historique des requêtes précédentes

	// le modèle de requête vierge
	// on peut y garder le token de session car il n'est pas censé changer
	this.queryObject = {
		"func": null,
		"token": this.token,
		"objName": null,
		"having": [],
		"sorting": [],
		"properties": {
			"include": [],
			"exclude": []
		},
		"boundaries": {
			"offset": 0,
			"batch": 50
		}
	};

	// créer une copie de travail du modèle
	this.query = jQuery.extend(true, {}, this.queryObject);

	// définir le type d'objet voulu (class)
	this.setObject = function(name) {
		this.objName = name;
		return this;
	};

	// changer le type de fonction
	this.setFunction = function(name) {
		if (name==null) return this;
		this.func = name;
		return this;
	}

	// ajouter des conditions (having)
	// "val" peut être une chaine ou un tableau avec deux chaines représentant des bornes basse (0) et haute (1)
	// @TODO vérifier / améliorer cette gestion des bornes
	// @TODO ajouter la récursion des conditions
	this.having = function(prop, oper, val, andor) {
		
		// ne rien faire si les arguments sont absents
		if (prop==null || oper==null) return this;
		
		// val peut être NULL mais doit alors être converti en chaine
		val = val==null? 'NULL': val; 
		if (typeof val == 'object') {
			having = {property: prop, operator: oper, value: val[0], and: val[1]};
		} else {
			having = {property: prop, operator: oper, value: val};
		}

		if (typeof andor == 'object') { // null si absent
			if (typeof andor.assoc == 'string') { // AND ou OR
				having = {
					property: prop,
					operator: oper,
					value: andor.val,
					assoc: {
						assoc: andor.assoc,
						property: andor.prop,
						operator: andor.oper,
						value: andor.val
					}
				};
			}
		}
		
		this.query.having.push(having);
		
		return this;
	};


	// ajouter des limites (offset, limit)
	this.boundaries = function(offset, batch) {
		
		this.query.boundaries.offset = isNaN(offset)? this.queryObject.boundaries.offset: offset;
		this.query.boundaries.batch = isNaN(batch)? this.queryObject.boundaries.batch: batch;

		return this;
	};

	// ajouter des filtres (properties)
	// "prop" peut être une chaine ou un tableau de chaines

	//   inclusion explicite (gérer l'exclusion implicite de tout le reste côté serveur)
	this.include = function(prop) {

		switch (typeof prop) {
			case 'object':
				this.query.properties.include = this.query.properties.include.concat(prop);
			break;
			case 'string':
				this.query.properties.include.push(prop);
			break;
			default:
				return this;
			break;
		}
		return this;
	};

	//   exclusion
	this.exclude = function(prop) {

		switch (typeof prop) {
			case 'object':
				this.query.properties.exclude = this.query.properties.exclude.concat(prop);
			break;
			case 'string':
				this.query.properties.exclude.push(prop);
			break;
			default:
				return this;
			break;
		}
		return this;
	};

	// ajouter un tri (order)
	this.sorting = function(prop, ord) {
		if (typeof prop != 'string') return this;
		if (ord==null) ord = 'ASC';

		this.query.sorting.push({
			property: prop,
			order: ord
		});
		return this;
	};

	// archiver la requête et recommencer
	// @TODO? un paramètre pour détruire la requête sans l'archiver?
	this.reset = function() {
		this.query.objName = this.objName;
		this.query.token = this.token;

		var old = jQuery.extend(true, {}, this.query);
		this.queries.push(old);
		var old = null;
		this.query = jQuery.extend(true, {}, this.queryObject);
		return this;
	};

	// récupérer l'objet query finalisé
	this.getQuery = function(format) {
		format = (format==null)? 'JSON': format;
		format = 'JSON'; // on ne fait que du JSON

		if (this.objName==null) return false;
		if (this.token==null) return false;

		this.query.objName = this.objName;
		this.query.token = this.token;
		this.query.func = this.func;
		//console.log(this.query);
		return this.query;

	};

};

