// modulo globale dell'applicazione
(function($) {
	// bootstrap dell'applicazione
	$.appBootstrap = function(params)
	{
		// cliccando sul logo si va alla home page
		if (params.homeUrl)
			$("#logo").click(function() {
				window.location = params.homeUrl;
			});
	};

	$.toHex = function(nDec, iLength)
	{
		var result = nDec.toString(16);
		while (result.length < iLength)
			result = "0" + result;
		return result;
	};
	$.toColor = function(nColor)
	{
		return "#" + $.toHex(nColor, 6);
	};

	//-----------------------------------------------------------
	//		fixRatio
	// aggiusta i margini per mantenere un rapporto x/y costante
	//-----------------------------------------------------------
	$.fn.fixRatio = function(ratio)
	{
		// ciclo principale
		return this.each(function()
		{
			var oSelf = this;
			var $parent = $(this).parent();

			// metodo fnGetCssVal: recupera un parametro css se numerico ed espresso in pixel, altrimenti ritorna 0
			this.fnGetCssVal = function(key)
			{
				var val = $(this).css(key);
				if (val.match(/^(\d+)px;?$/i))
					return parseInt(val);
				else
					return 0;
			};

			// legge eventuali dimensioni minime
			var minWidth = this.fnGetCssVal("min-width");
			var minHeight = this.fnGetCssVal("min-height");

			// memorizza o richiama i margini originali
			if (!this.margins)
				this.margins = $(this).fnGetMargins();

			// dimensioni attuali
			var x = $parent.width() - this.margins.outerX;
			var y = $parent.height() - this.margins.outerY;
			var r = x / y;
			
			// aggiusta il ratio
			if (r > ratio)
				x = Math.max(minWidth, parseInt(y * ratio));
			else
				y = Math.max(minHeight, parseInt(x / ratio));

			// aggiorna i margini 
			x = parseInt(($parent.width() - x) / 2);
			y = parseInt(($parent.height() - y) / 2);
			$(this).css("margin", y + "px " + x + "px");				
		});
	};

	//--------------------------------------------------------
	$.fn.fnGetMargins = function()
	{
		var x = $(this).outerWidth(true);
		var y = $(this).outerHeight(true);
		return {
			outerX: x - $(this).outerWidth(),
			outerY: y - $(this).outerHeight(),
			innerX: x - $(this).width(),
			innerY: y - $(this).height()
		};
	};

	//--------------------------------------------------------
	$.fn.fnImageLoader = function(fnCompleted)
	{
		// filtra solo le immagini
		$images = $(this).filter("img");

		// ciclo principale
		return $images.each(function()
		{
			if (this.complete)
				// immagine già caricata
				fnCompleted(this);
			else
				// immagine in fase di caricamento
				$(this).load(function() {
					fnCompleted(this);
				});
		});
	};

	$.fn.loadAndFit = function(params)
	{
		if (typeof params == "string")
			params = {src: params};

		// filtra solo le immagini
		var $images = $(this).filter("img");
		
		// ciclo principale
		return $images.each(function()
		{
			var oSelf = this;
			if (params.parent)
				var oParent = params.parent;
			else
				var oParent = $(oSelf).parent();

			this.fnLoaded = function(e, ui) {
				if (params.parent)
					$(oParent).html(oSelf);
				$(oSelf)
					.fitImage()
					.show();
				$(oParent).removeClass("loading");
			};

			this.fnStart = function(e, ui) {
				if (!oSelf.complete) {
					$(oParent).addClass("loading");
					$(oSelf).hide();
				}
				$(oSelf).attr("src", params.src);
			};

			$({}).imageLoader({
				images: Array(params.src),
				start: oSelf.fnStart,
				allcomplete: oSelf.fnLoaded
			});
		});
	};

	//--------------------------------------------------------
	// §§§	in realtà fitImage potrebbe solo calcolare il ratio e
	//		poi richiamare  fixRatio... verificare se funziona
	$.fn.fitImage = function(params)
	{
//		// parametri di default
//		params = $.extend({
//			backColor: false
//		}, params);

		// filtra solo le immagini
		var $images = $(this).filter("img");

		// ciclo principale
		return $images.each(function()
		{
			var oSelf = this;

			// metodo fnResize: aggiusta dimensioni e margini
			this.fnResize = function(e, ui)
			{
				var $parent = $(this).parent();
				var natW = $(this).width();
				var natH = $(this).height();

				// aggiusta il colore di fondo, se richiesto
				var backColor = $(oSelf).data("backColor");
				if (backColor)
					$parent.css("background-color", backColor);
//				else
//					$parent.css("background-color", "");

				// memorizza o richiama i margini originali
				if (!this.margins)
					this.margins = $(this).fnGetMargins();

				var w = ($parent.width() - this.margins.innerX);
				var h = ($parent.height() - this.margins.innerY);
				var rx = w / natW;
				var ry = h / natH;
				if (rx < ry)
				{
					var h1 = parseInt(natH * rx);
					var mx = parseInt(this.margins.outerX / 2);
					var my = parseInt((this.margins.outerY + (h - h1)) / 2);
					h = h1;
				}
				else
				{
					var w1 = parseInt(natW * ry);
					var mx = parseInt((this.margins.outerX + (w - w1)) / 2);
					var my = parseInt(this.margins.outerY / 2);
					w = w1;
				}

				// ridimensionamento
				$(this).width(w);
				$(this).height(h);
				$(this).css("margin", my + "px " + mx + "px");
			};

			// carica l'immagine
			if ($(this).attr("src"))
				this.fnResize();
/*
			{
				// N.B. fnResize potrebbe essere richiamato 2 volte: pazienza.
				$(this).load(function() {
					this.fnResize();
				});
				if (this.complete)
					this.fnResize();
			}
*/
		});
	};

	//--------------------------------------------------------
	$.fnShowButtons = function(buttons)
	{
		// ciclo
		for (b in buttons)
			$("#btn_" + b).removeClass("hidden")
				.linkButton(buttons[b])
				.show();
	};

	//--------------------------------------------------------
	$.fn.stateButton = function(params)
	{
		this.anchor = function() {
			var url = $(this).attr("href");
			if (url)
				$(this).removeAttr("href")
					.click(function() {
						window.location = url;
					});
			return this;
		};

		this.disable = function() {
			$(this)
				.removeClass("btn-hover")
				.addClass("btn-disabled");

			return this;
		};

		this.enable = function() {
			$(this).removeClass("btn-disabled");
			return this;
		};

		this.isDisabled = function()
		{
			return $(this).hasClass("btn-disabled");
		};

		this.setEnabled = function(bValue) {
			if (bValue === false)
				return this.disable();
			else
				return this.enable();
		};

		this.stateDown = function() {
			$(this).addClass("btn-down");
			return this;
		};

		this.stateUp = function() {
			$(this).removeClass("btn-down");
			return this;
		};

		return this.each(function()
		{
			$(this).hover(
				function() {
					if (!$(this).hasClass("btn-disabled"))
						$(this).addClass("btn-hover");
				},
				function() {
					$(this).removeClass("btn-hover");
				}
			);
		});
	};

	//---------------------------------------------------------
	$.fn.linkButton = function(params)
	{
		// metodi pubblici
		if (params == "disable")
			return this.each(function() { this.fnDisable(); });
		else if (params == "enable")
			return this.each(function() { this.fnEnable(); });
		else if (params == "toggle")
			return this.each(function() { this.fnToggleState(); });

		// parametri di default
		params = $.extend({
			disabled: false
		}, params);

		// ciclo principale
		return this.each(function()
		{
			// var oSelf = this;

			//-----  INTERFACCIA  -----

			this.fnDisable = function()
			{
				this.disabled = true;
				this.fnUpdateState();
			};

			this.fnEnable = function()
			{
				this.disabled = false;
				this.fnUpdateState();
			};

			this.fnToggleState = function()
			{
				this.disabled = !this.disabled;
				this.fnUpdateState();
			};

			this.fnUpdateState = function()
			{
				$(this).unbind();
				if (this.disabled)
				{
					$(this).css("background-position", this.disabledState);
					$(this).click(function(event) { event.preventDefault(); });
				}
				else
				{
					$(this).css("background-position", this.normalState);
					$(this).click(function(event) {
						event.preventDefault();
						if (this.clickCallback)
							this.clickCallback(this);
						else
							window.location = this.clickUrl;
					})
					.hover(
						function() {
							$(this).css("background-position", this.hoverState);
						},
						function() {
							$(this).css("background-position", this.normalState);
						}
					)
					.mousedown(function() {
						$(this).css("background-position", this.downState);
					})
					.mouseup(function() {
						$(this).css("background-position", this.hoverState);
					});
				}
			};

			//-----  IMPLEMENTAZIONE  -----

			if (params.clickUrl)
				this.clickUrl = params.clickUrl;
			else
				this.clickUrl = $(this).attr("href");
			$(this).removeAttr("href");

			if (params.clickCallback)
				this.clickCallback = params.clickCallback;

			var h = $(this).height();
			this.normalState = "0 0";
			this.hoverState = "0 -" + h + "px";
			this.downState = "0 " + h * 2 + "px";
			this.disabledState = "0 " + h + "px";

			this.disabled = params.disabled;
			this.fnUpdateState();
		});
	};

	//---------------------------------------------------------
	// Risolve un problema di Scrollable di jQueryTools quando
	// ci sono più oggetti scrollable nella stessa pagina
	$.fn.scrollable2 = function(params)
	{
		var i = 1;
		return this.each(function() {
			var next = (params.next) ? params.next : ".next";
			var $next = $(next, $(this).parent().parent());
			var prev = (params.prev) ? params.prev : ".prev";
			var $prev = $(prev, $(this).parent().parent());

			var iBlocks = $(".var_block", this).length;
			if (iBlocks < 2)
			{
				$next.hide();
				$prev.hide();
			}
			else
			{
				var cls = $next.attr("class");
				cls += " " + next.slice(1) + i;
				$next.attr("class", cls);
	
				var cls = $prev.attr("class");
				cls += " " + prev.slice(1) + i;
				$prev.attr("class", cls);
	
				var params2 = {};
				$.extend(params2, params);
				$.extend(params2, {next: next + i, prev: prev + i});
				$(this).scrollable(params2);
			}
			i++;
		});
	};
})(jQuery);

