/*
@name: htdocs/js/sms/rubrica.js
@desc: Componente per rubrica contatti
@authors: Marco Biondi
@lastauthor: Marco Biondi

	Mapping errori
	0 : Ajax request fallita
	1 : Record inesistente
	2 : Chiave primaria duplicata
*/
var Contatto = Class.create();
Contatto.prototype = {
	initialize: function() {},
	nome: '',
	cognome: '',
	numero: '',
	nick: '',
	email: '',
	note: '',
	folder: -1,
	sel: false,
	ref: null,
	idT: -1,
	id: -1,
	sortOn: 'cognome',
	dset: ['nome', 'cognome', 'numero', 'nick', 'email', 'note', 'folder', 'sel', 'idT', 'id'],
	dtyp: ['S', 'S', 'S', 'S', 'S', 'S', 'I', 'B', 'I', 'I'],
	toString: function(){
		return(this[this.sortOn]);
	},
	setSort: function(campo){
		if(typeof(campo) == "string" && typeof(this[campo]) == "string")
			Contatto.prototype.sortOn = campo;
	},
	update: function(dati){
		var i;
		for(i=0; i<this.dset.length; i++)
		{
			if(typeof(dati[this.dset[i]]) != 'undefined')
			{
				switch(this.dtyp[i])
				{
					case 'B':
						this[this.dset[i]] = Boolean(dati[this.dset[i]]);
						break;
					case 'I':
						this[this.dset[i]] = parseInt(dati[this.dset[i]]);
						break;
					default:
						this[this.dset[i]] = String(dati[this.dset[i]]);
						break;
				}
			}
		}
	},
	formatTip: function(expr, localP){
		var res = '';
		if(expr instanceof RegExp)
		{
			if(this.nick != '')
				res += this.nick.replace(expr,"<b>$&</b>")+" - ";
			if(this.nome != '')
				res += this.nome.replace(expr,"<b>$&</b>")+" ";
			if(this.cognome != '')
				res += this.cognome.replace(expr,"<b>$&</b>")+" - ";
			
			res += this.numero.replace(expr,"<b>$&</b>");
		}
		else
		{
			res += '"';
			if(this.nick != '')
				res += this.nick+" - ";
			if(this.nome != '')
				res += this.nome+" ";
			if(this.cognome != '')
				res += this.cognome;
			res += '" - ';

			res += "<"+this.numero+">";
		}

		if(localP)
			res = res.replace(RegExp("\\"+localP), '');
		return(res);
	},
	dump: function(){
		var s = "";
		for(var i in this)
		{
			if(typeof(this[i]) == "string")
				s += i+" : "+this[i]+"\n";
		}
		return(s);
	},
	clone: function(obj)
	{
		var i;
		for(i=0; i<this.dset.length; i++)
			obj[this.dset[i]] = this[this.dset[i]];
	}
}

var Rubrica = Class.create();
Rubrica.prototype = {
	initialize: function(errorMap, debugArea) {
		this.isInitialized = false;
		this.noupdate = false;
		this.autoinc = 0;
		this.urls = {getA: "/sms/getrub.php", modA: "/sms/modrub.php"};
		this.debug = debugArea;
		this.sortOn = "cognome";
		this.sortDir = 1;
		this.defPrefix = "";
		this.rubType = "";
		this.rubri = new Array();
		this._validNumber = null;
		this._errorsArr = errorMap;

		//Al momento la gestione è statica (0 cestino, 1 Default)
		this._folders = new Array('cestino','default');

		this._selection = new Array();
		this._curView = null;
		this._viewType = -1;	//-1 tutto, -2 Selection

		if(this.debug)
			this.debug.value = "";

		EventBroadcaster.initialize(this);

		this.options = {};
		this.options.onComplete = this.parseResponse.bind(this);
		this.options.onFailure = this.rFailed.bind(this);
		this.options.onException = this.ajException.bind(this);
		this.rubriAjax = new Ajax.Request( this.urls.getA, this.options);
	},

	ajException: function(request, exception)	{
		throw(exception);
	},

	addContact: function(dati) {
		var arr = new Array(dati);
		return(this.addContacts(arr));
	},

	addContacts: function(arrd) {
		if(!this.isInitialized)
			return(false);

		var i, params, foo, bar, idres, target, opt, ax;
		params = '';
		idres = new Array();

		for(i = 0; i < arrd.length; i++)
		{
			this.normalizeData(arrd[i]);
			params += "numeri[]="+escape(arrd[i].numero)+"&";
			params += "nomi[]="+escape(arrd[i].nome)+"&";
			params += "cognomi[]="+escape(arrd[i].cognome)+"&";
			params += "nick[]="+escape(arrd[i].nick)+"&";
			params += "mail[]="+escape(arrd[i].email)+"&";
			params += "note[]="+escape(arrd[i].note)+"&";
			params += "gruppi[]="+escape(arrd[i].folder)+"&";
		}

		params += 'modo=add';

		if(this.noupdate)
		{
			for(i = 0; i < arrd.length; i++)
				idres.push(this.autoinc++);
		}
		else
		{
			opt = {
				asynchronous: false,
				parameters: params.replace(/\+/,"%2b")
				};
	
			ax = new Ajax.Request( this.urls.modA, opt);
			if(ax.transport.status == 200)
			{
				foo = ax.transport.responseXML.getElementsByTagName("risposta");
				if(foo[0])
				{
					Element.cleanWhitespace(foo[0]);
					bar = foo[0].firstChild;
					if(bar.nodeName != "risultato")
						return(false);
					if(bar.firstChild.nodeValue != 1)
						return(false);
					bar = bar.nextSibling;
					while(bar)
					{
						idres.push(bar.firstChild.nodeValue);
						bar = bar.nextSibling;				
					}
				}
				else
					return(false);	//Parsare il tag errore
			}
			else
				return(false);
		}

		for(i = 0; i < arrd.length; i++)
		{
			target = new Contatto();
			target.update(arrd[i]);
			target.id = parseInt(idres[i]);
			target.idT = this.rubri.length;
			target.ref = target;
			this.rubri.push(target);
			if((this._viewType == -1) || (this._viewType == target.folder))
				this._curView.push(target);
		}

		this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
		return(true);
	},

	delContact: function(id) {
		if(!this.isInitialized)
			return(false);

		var target = this.getContact(id);
		target.ref = null;
		for(var i=0; i < this.rubri.length; i++)
		{
			if(target == this.rubri[i])
			{
				this.rubri.splice(i,1);
				break;
			}
		}
		//TODO: Send ajax request for delete.
		delete(target);
		this.dispatchEvent({type: "onDataChange", dEvType: "delete", from: i, to: i});
	},

	modContact: function(id,dati) {
		dati['id'] = id;
		var arr = new Array(dati);
		return(this.modContacts(arr));
	},

	modContacts: function(arrd) {
		if(!this.isInitialized)
			return(false);

		var i, params, foo, bar, idres, target, opt, ax;
		try
		{
			params = '';

			for(i = 0; i < arrd.length; i++)
			{
				this.normalizeData(arrd[i]);
				target = this.getContact(arrd[i].id);
				params += "id[]="+escape(target.id)+"&";
				params += "numeri[]="+escape(arrd[i].numero)+"&";
				params += "nomi[]="+escape(arrd[i].nome)+"&";
				params += "cognomi[]="+escape(arrd[i].cognome)+"&";
				params += "nick[]="+escape(arrd[i].nick)+"&";
				params += "mail[]="+escape(arrd[i].email)+"&";
				params += "note[]="+escape(arrd[i].note)+"&";
				params += "gruppi[]="+escape(arrd[i].folder)+"&";
			}

			params += 'modo=mod';

			if(!this.noupdate)
			{
				opt = {
					asynchronous: false,
					parameters: params.replace(/\+/,"%2b")
					};
		
				ax = new Ajax.Request( this.urls.modA, opt);
				if(ax.transport.status == 200)
				{
					foo = ax.transport.responseXML.getElementsByTagName("risposta");
					if(foo[0])
					{
						Element.cleanWhitespace(foo[0]);
						bar = foo[0].firstChild;
						if(bar.nodeName != "risultato")
							return(false);
						if(bar.firstChild.nodeValue != 1)
							return(false);
					}
					else
						return(false);	//Parsare il tag errore
				}
				else
					return(false);
			}

			for(i = 0; i < arrd.length; i++)
				target.update(arrd[i]);

			this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
			return(true);
		}
		catch(err)
		{
			alert(err);
			return(false);
		}
	},

	getContact: function(id) {
		var res = null;
		if(id instanceof Contatto)
			res = id;
		else if(typeof(id) == "number")
			res = this.rubri[id];

		if(res)
			return(res);
		else
			throw(new Error(1));
	},

	getContactList: function() {
	},

	getContactTips: function(hint, callbackC, callbackO) {
		if(typeof(hint) != "string" || hint == "" || hint == "+" || hint == "00")
		{
			if(this._viewType == -2)
			{
				this.clearSelection(true);
				if(this._curView)
					delete(this._curView);
				this._curView = new Array();
				this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
			}
			return(null);
		}
		var isNum = false;
		var regX = /^(\+|\d)/;
		if(regX.test(hint))
		{
			isNum = true;

			if(hint.substr(0,2) == "00")
				hint = "+"+hint.substr(2);

			if(hint.charAt(0) != "+")
				hint = this.defPrefix+hint;
		}
		var convX = /(\\|\+|\||\?|\*|\(|\)|\{|\}|\^|\$|\.|\[|\]|\/)/g;
		var findX = new RegExp("^"+hint.replace(convX, "\\$1"),"i");
		var target = this.rubri;

		var res = new Array();
		for(var i=0; i<target.length && res.length<20; i++)
		{
			if(isNum)
			{
				if(findX.test(target[i].numero))
					res.push(target[i]);
			}
			else
			{
				if(this._viewType == -2)
				{
					if(findX.test(target[i].nome) || findX.test(target[i].cognome))
						res.push(target[i]);
				}
				else
				{
					if(findX.test(target[i].nome) || findX.test(target[i].cognome) || findX.test(target[i].nick))
						res.push(target[i]);
				}
			}
		}

		if(this.debug)
		{
			this.debug.value = "";
			for(i=0; i<res.length; i++)
				this.debug.value += res[i].formatTip(findX,this.defPrefix)+"\n";
		}

		if(typeof(callbackC) != "string" &&	this._viewType == -2)
		{
			this.clearSelection(true);
			if(this._curView)
				delete(this._curView);
			this._curView = res;
			this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
			return(true);
		}
		else
		{
			var resF = "";
			for(i=0; i<res.length; i++)
			{
				resF += "<p id='tip_"+res[i].idT+"' onclick='"+callbackC+"(this)' onmouseover='"+callbackO+"(this)' onmousemove='"+callbackO+"(this)'>"+res[i].formatTip(findX,this.defPrefix)+"</p>";
			}
			return(resF);
		}
	},

	normalizeData: function(dati) {
		if(typeof(dati.numero) == 'undefined')
			dati.numero = '';
		if(typeof(dati.nome) == 'undefined')
			dati.nome = '';
		if(typeof(dati.cognome) == 'undefined')
			dati.cognome = '';
		if(typeof(dati.nick) == 'undefined')
			dati.nick = '';
		if(typeof(dati.email) == 'undefined')
			dati.email = '';
		if(typeof(dati.note) == 'undefined')
			dati.note = '';
		if(typeof(dati.folder) == 'undefined')
			dati.folder = 1;

		if(dati.numero.substr(0,2) == "00")
			dati.numero = "+"+dati.numero.substr(2);

		if(dati.numero.charAt(0) != "+")
			dati.numero = this.defPrefix+dati.numero;
	},

	findContact: function(num) {
		if(num.charAt(0) != "+")
			num = this.defPrefix+num;
		for(var i = 0; i < this.rubri.length; i++)
		{
			if(this.rubri[i].numero == num)
				return(this.rubri[i]);
		}
		return(null);
	},

	isValidNumber: function(num) {
		if(num.substr(0,2) == "00")
			return(this._validNumber.test("+"+num.substr(2)));
		else
			return(this._validNumber.test(num));
	},

	parseResponse: function(originalRequest) {

		var foo,bar;
		if(this.debug)
		{
			this.debug.value = originalRequest.responseText;
		}

		try
		{
			foo = originalRequest.responseXML.getElementsByTagName("rubrica");
			this.defPrefix = foo[0].getAttribute('defPrefix');
			this.rubType = foo[0].getAttribute('type');
			if(foo[0].getAttribute('noupdate'))
				this.noupdate = true;
	
			if(this.rubType == 'local')
				this._validNumber = new RegExp("^(\\"+this.defPrefix+")?\\d{9,13}$");
			else
				this._validNumber = /^\+\d{12,15}$/;
	
			foo = originalRequest.responseXML.getElementsByTagName("voce");
			for(i=0; i < foo.length; i++)
			{
				this.rubri[i] = new Contatto();
				this.rubri[i].ref = this.rubri[i];
				this.rubri[i].idT = i;
				bar = foo[i].firstChild;
				while(bar)
				{
					if(bar.nodeType == 1)
					{
						if(bar.firstChild)
							this.rubri[i][bar.nodeName] = bar.firstChild.nodeValue;
					}
					bar = bar.nextSibling;
				}
			}
	
			if(this.noupdate)
				this.autoinc = this.rubri.length;
	
			this.isInitialized = true;
			this.setView(-1);		//Default view tutto
		}
		catch(err)
		{
			//Killo tutto
			this.isInitialized = false;
			this.rubri = new Array();
			this._curView = null;
			this.noupdate = true;
			this.defPrefix = "";
			this.rubType = "error";
		}

		if(!this.isInitialized)
		{
			//La rubrica non è stata scaricata accetto solo numeri senza prefisso!!!
			this._validNumber = /^\d{10,13}$/;
		}
	},

	setView: function(id) {
		if(this.isInitialized)
		{
			this.clearSelection(true);
	
			if(this._curView)
			{
				delete(this._curView);
				this._curView = null;
			}
	
			this._curView = new Array();
	
			if(id < 0 || id >= this._folders.length)
			{
				if(id == -2)
				{
					//Modo filter
					this._viewType = -2;
				}
				else
				{
					//Mostro tutto ma non il cestino
					for(var i=0; i<this.rubri.length; i++)
					{
						if(this.rubri[i].folder != 0)
							this._curView.push(this.rubri[i]);
					}
					this._viewType = -1;
				}
			}
			else
			{
				//Mostro quello richiesto
				for(var i=0; i<this.rubri.length; i++)
				{
					if(this.rubri[i].folder == id)
						this._curView.push(this.rubri[i]);
				}
				this._viewType = id;
			}
	
			this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
		}
	},

	sortData: function(field, dir) {
		if(typeof(field) == "string")
			this.sortOn = field;
		if(typeof(dir) == "number")
			this.sortDir = dir;

		Contatto.prototype.setSort(this.sortOn);

		this._curView.sort();
		if(this.sortDir < 0)
			this._curView.reverse();
	},

	clearSelection: function(nodispatch) {
		var i;
		for(i=0; i < this._selection.length; i++)
		{
			this.rubri[this._selection[i]].sel = false;
		}

		this._selection.splice(0,this._selection.length);

		this.dispatchEvent({type: "onSelChange"});

		if(!nodispatch)
			this.dispatchEvent({type: "onDataChange", dEvType: "updateAll"});
	},

	alterSelection: function(id,nodispatch) {
		var i;
		var obj = this._curView[id];
		if(obj)
		{
			for(i=0; i < this._selection.length; i++)
			{
				if(this._selection[i] == obj.idT)
				{
					this._selection.splice(i,1);
					break;
				}
			}
	
			if(obj.sel)
				this._selection.push(obj.idT);
	
			this.dispatchEvent({type: "onSelChange"});

			if(!nodispatch)
				this.dispatchEvent({type: "onDataChange", dEvType: "update", from: id});
		}
	},

	getSelLen: function() {
		return(this._selection.length);
	},

	getIDSelected: function() {
		return(this._selection);
	},

	getSelected: function() {
		var i;
		var foo= new Array();
		for(i=0; i < this._selection.length; i++)
			foo.push(this.rubri[this._selection[i]]);
		return(foo);
	},

	rFailed: function(originalRequest) {
		if(this._errorsArr)
		{
			alert(this._errorsArr[0]);
		}
		else
			throw(new Error(0));
	},

	dump: function() {
		var i,j,s;
		if(this.isInitialized)
		{
			if(this.debug)
				this.debug.value = this.defPrefix+"\n";
			else
				alert(this.defPrefix);

			for(i=0; i < this.rubri.length; i++)
			{
				s = i+"\n"+this.rubri[i].dump();
				
				if(this.debug)
					this.debug.value += s+"\n";
				else
					alert(s);
			}
		}
		else
		{
			alert("Rubrica non caricata");
		}
	},

	getLocalNumber: function(num)
	{
		if(num.substr(0,this.defPrefix.length) == this.defPrefix)
			return(num.substr(this.defPrefix.length));
		else
			return(num);
	},

	getLength: function() {
		if(this._curView)
			return(this._curView.length);
		else
			return(0);
	},

	getItemAt: function(id) {
		if(this._curView)
		{
			if(this._curView[id])
			{
				var res = new Object();
				this._curView[id].clone(res);
				res.numero = this.getLocalNumber(res.numero);
				return(res);
			}
		}
		return(null);
	},

	setField: function(id, field, dato) {
		//TODO: Aggiungere update base dati sul server
		if(this._curView)
		{
			var foo = this._curView[id];
			if(foo)
			{
				if(field == 'numero')
				{
					if(!this.isValidNumber(dato))
						return(false);
				}
	
				foo[field] = dato;
				if(field == 'sel')
					this.alterSelection(id,true);
				this.dispatchEvent({type: "onDataChange", dEvType: "update", from: id});
				return(true);
			}
		}
		return(false);
	}
}
