var Gradimento = new Object();
Gradimento.Lista = Class.create({
	container: null,
	items: null,	
	_img: null,
	_cookieName: "vinit_prefs",
	cookieData: null,
	cookieOpts: [],
								
	initialize: function(container, urlVoto, options) {
		this.container = $(container);
		this.items = new Array();
		this.urlVoto = urlVoto;
		this._img = (options.img == null) ? {"okOn": "okOn.gif", "noOn": "noOn.gif", "okOff": "okOff.gif", "noOff": "noOff.gif"} : options.img;
		this.cookieOpts = (options.cookieOpts == null) ? [] : options.cookieOpts;
		
		// Prende i dat i del cookie:
		Cookie.init({name: this._cookieName, path: "/"});
		this.retrieveCookieData();
				
		// Tutti gli item della lista:
		var elements = this.container.getElementsBySelector(".item");
			
		$A(elements).each(
			function(item) {
				this.items.push(new Gradimento.Item(item, this, {}));
			}.bind(this)
		);
	},
	
	retrieveCookieData: function() {
		try {
			this.cookieData = base64_decode(Cookie.data).evalJSON();					
		} catch (e) {
			this.cookieData = null;
		}
	},
	
	setCookieData: function(data) {
		this.cookieData = data;
	}
});        

Gradimento.Item = Class.create({
	_element: null,
	_img: null,
	_okA: null,
	_okImg: null,
	_noA: null,
	_noImg: null,
	_ref: null,
	_created: false,
	_voto: null,
	
	initialize: function(container, lista, options) {
		this.container = $(container);
		this.lista = $(lista);
		this._ref = this.container.readAttribute("ref");
							
		// Crea l'elemento:
		this._create();
	},
	
	_create: function() {
		if (!this._created) {
			this._element = new Element("span");
		}
		
		this._okImg = new Element("img", { "src": this.lista._img.okOff});
		this._noImg = new Element("img", { "src": this.lista._img.noOff});
		
		this._okA = new Element("a", {"href": "#null", "title": "Mi piace"}).update(this._okImg);
		this._noA = new Element("a", {"href": "#null", "title": "Non mi piace"}).update(this._noImg);
		
		if (this._hasCookie()) {
			if (this._voto == 1) { 
				this._element.insert(new Element("img", { "src": this.lista._img.okOn}));
			} else {
				this._element.insert(new Element("img", { "src": this.lista._img.noOn}));
			}
		} else {
			Element.observe(this._okA, "mouseover", this._mouseOverOk.bind(this));
			Element.observe(this._okA, "mouseout", this._mouseOutOk.bind(this));
			
			Element.observe(this._noA, "mouseover", this._mouseOverNo.bind(this));
			Element.observe(this._noA, "mouseout", this._mouseOutNo.bind(this));
			
			Element.observe(this._okA, "click", this._clickSi.bind(this));
			Element.observe(this._noA, "click", this._clickNo.bind(this));
			
			this._element.insert(this._okA);
			this._element.insert(this._noA);
		}
							
		if (!this._created) {
			this.container.insert({ after: this._element});
			this._created = true;
		}
	},
	
	_delete: function() {
		Element.stopObserving(this._okA);					
		Element.stopObserving(this._noA);
		
		this._element.update();
		this._okImg = null;
		this._noImg = null;
		this._okA = null;
		this._noA = null;
	},
	
	_hasCookie: function() {
		if (this.lista.cookieData == null) {
			return false;
		}
		
		var data = this.lista.cookieData;
		var opts = this.lista.cookieOpts;
							
		for (i=0; i<opts.length; i++) {						
			 if (data[opts[i]] == null) {
				return false; 
			 }
			 var data = data[opts[i]];
		}
				
		if (data[this._ref] == null) {
			return false;
		}
		
		if (data[this._ref] == 1) {
			this._voto = 1; // Voto positivo.
		} else {
			this._voto = -1; // Voto negativo.
		}
		
		return true;
	},
	
	_mouseOverOk: function() {
		this._okImg.writeAttribute("src", this.lista._img.okOn);
	},
	
	_mouseOutOk: function() {
		this._okImg.writeAttribute("src", this.lista._img.okOff);
	},
	
	_mouseOverNo: function() {
		this._noImg.writeAttribute("src", this.lista._img.noOn);
	},
	
	_mouseOutNo: function() {
		this._noImg.writeAttribute("src", this.lista._img.noOff);
	},
	
	_clickSi: function() {
		this._richiestaVoto(1);
	},
	
	_clickNo: function() {
		this._richiestaVoto(-1);
	},
	
	_richiestaVoto: function(voto) {
		new Ajax.Request(this.lista.urlVoto, {
			postBody: "voto=" + parseInt(voto) + "&ref=" + encodeURIComponent(this._ref),
			evalJSON: true,
			onFailure: function() {
				alert("E' occorso un errore durante il salvataggio del voto...");							
			},
			onSuccess: function(r) {
				this.lista.setCookieData(r.responseJSON);
				this._delete();
				this._create();
			}.bind(this),
			on401: function() {
				alert("Hai già espresso il tuo voto per questo elemento.");
			}
		});
	}
});


function base64_decode (data) {
	// Decodes string using MIME base64 algorithm  
	// 
	// version: 909.322
	// discuss at: http://phpjs.org/functions/base64_decode
	// +   original by: Tyler Akins (http://rumkin.com)
	// +   improved by: Thunder.m
	// +      input by: Aman Gupta
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   bugfixed by: Onno Marsman
	// +   bugfixed by: Pellentesque Malesuada
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +      input by: Brett Zamir (http://brett-zamir.me)
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// -    depends on: utf8_decode
	// *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
	// *     returns 1: 'Kevin van Zonneveld'
	// mozilla has this native
	// - but breaks in 2.0.0.12!
	//if (typeof this.window['btoa'] == 'function') {
	//    return btoa(data);
	//}

	var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = "", tmp_arr = [];

	if (!data) {
		return data;
	}

	data += '';

	do {  // unpack four hexets into three octets using index points in b64
		h1 = b64.indexOf(data.charAt(i++));
		h2 = b64.indexOf(data.charAt(i++));
		h3 = b64.indexOf(data.charAt(i++));
		h4 = b64.indexOf(data.charAt(i++));

		bits = h1<<18 | h2<<12 | h3<<6 | h4;

		o1 = bits>>16 & 0xff;
		o2 = bits>>8 & 0xff;
		o3 = bits & 0xff;

		if (h3 == 64) {
			tmp_arr[ac++] = String.fromCharCode(o1);
		} else if (h4 == 64) {
			tmp_arr[ac++] = String.fromCharCode(o1, o2);
		} else {
			tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
		}
	} while (i < data.length);

	dec = tmp_arr.join('');
	dec = this.utf8_decode(dec);

	return dec;
}

function utf8_decode ( str_data ) {
	// Converts a UTF-8 encoded string to ISO-8859-1  
	// 
	// version: 909.322
	// discuss at: http://phpjs.org/functions/utf8_decode
	// +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
	// +      input by: Aman Gupta
	// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// +   improved by: Norman "zEh" Fuchs
	// +   bugfixed by: hitwork
	// +   bugfixed by: Onno Marsman
	// +      input by: Brett Zamir (http://brett-zamir.me)
	// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	// *     example 1: utf8_decode('Kevin van Zonneveld');
	// *     returns 1: 'Kevin van Zonneveld'
	var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0;
	
	str_data += '';
	
	while ( i < str_data.length ) {
		c1 = str_data.charCodeAt(i);
		if (c1 < 128) {
			tmp_arr[ac++] = String.fromCharCode(c1);
			i++;
		} else if ((c1 > 191) && (c1 < 224)) {
			c2 = str_data.charCodeAt(i+1);
			tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
			i += 2;
		} else {
			c2 = str_data.charCodeAt(i+1);
			c3 = str_data.charCodeAt(i+2);
			tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
			i += 3;
		}
	}

	return tmp_arr.join('');
}
