var ToolTip = { };

ToolTip.Base = Class.create();
ToolTip.Base.prototype =
{
  initialize: function(link, tooltip,options)
	{
    var options = Object.extend(
		{
			delta_x: 14,
			delta_y: 15,
			zIndex: 1000,
			defaultClass: 'tooltip',
			centrato: false,
			hideAfter : 0,
			showAfter : 0,
			hook : '',
			showOnClick : false,
			fix_x:'',
			fix_y:'',
			setStyle : true,
			keepPosition: false,
			ajaxUrl : '',
			ajaxLoader : '/image/loader.gif',
			onAjaxComplete : false
		}, options || {});

    this.link = $(link);
		this.options = options;
		this.tooltip = tooltip;
		this.callback = $A([]);
		this.old = $A([]);
		this.old.x = 0;
		this.old.y = 0;
		this.visible = false;

		if (!this.options.setStyle)
			this.options.keepPosition = false;

		// Se devo legare il tip a qualcosa
		if (this.options.hook != '')
		{
			if (this.options.hook.obj)
				this.options.hook.obj = $(this.options.hook.obj);
			else
				this.options.hook.obj = this.link;
		}




		// Faccio il bind delle funzioni
    this.eventMouseOver 		= this.showTooltip.bindAsEventListener(this,false);
		this.eventMouseClick 		= this.showTooltip.bindAsEventListener(this,true);
    this.eventMouseMove 		= this.moveTooltip.bindAsEventListener(this);
    this.eventMouseOut      = this.hideTooltip.bindAsEventListener(this);
		this.eventEndInactivity = this.endInactivity.bindAsEventListener(this);
		this.eventDelayedShow 	= this.delayedShow.bindAsEventListener(this);
		this.eventMouseTipOver	= this.tooltipOver.bindAsEventListener(this);
		this.eventMouseTipOut 	= this.tooltipOut.bindAsEventListener(this);
		this.eventKeepPosition 	= this.keepPosition.bindAsEventListener(this);

		// Azzero i vari intervalli e settaggi allo start
		this.interval = '';
		this.keepInterval = '';
		this.inactivity = '';
		this.activity = '';
		this.primoPosOk = false;
		this.inizializzato = false;
		this.inLink = false;
		this.inTooltip = false;

		// Registro i vari eventi
    this.registerEvents();
  },

	isIE : function()
	{
		return false;
		return /msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent);
	},
	getLoader: function()
	{
		var load = new Element('img', { src: this.options.ajaxLoader});
		return load;
	},

  destroy : function()
	{
		// Tolgo gli osservatori sui vari eventi
    Event.stopObserving(this.link, "mouseover", this.eventMouseOver);
		Event.stopObserving(this.link, "click", this.eventMouseClick);
		Event.stopObserving(this.link, "mousemove", this.eventMouseMover);
    Event.stopObserving(this.link, "mouseout", this.eventMouseOut);
		// Se ho creato il div, lo elimino
		if (this.tooltip)
			this.tooltip.parentNode.removeChild(this.tooltip);
		// Pulisco gli interval
		clearInterval(this.keepInterval);
		clearInterval(this.interval);
		clearInterval(this.activity);
		clearInterval(this.inactivity);

  },

  registerEvents : function()
	{
		// Registro i vari eventi
    Event.observe(this.link, "mouseover", this.eventMouseOver);
		Event.observe(this.link, "mouseout", this.eventMouseOut);

		if (this.options.hideAfter == 0)
			Event.observe(this.link, "mousemove", this.eventMouseMove);
		if (this.options.showOnClick)
			Event.observe(this.link, "click", this.eventMouseClick);
  },

	moveTooltip : function(event)
	{
		// Se si sta muovendo il mouse, lo seguo
		Event.stop(event);
		this.posiziona(event);
	},


	keepPosition : function ()
	{
		clearInterval(this.keepInterval);
		if (this.tooltip.visible())
		{
			// Allora reitero il keep position

			// Riposiziono
			this.posiziona();

			if (this.options.keepPosition)
				this.keepInterval = setInterval(this.eventKeepPosition,500);

			if (this.options.debug)
				console.log('keep position');
		}
		else
			console.log('no keep position');
	},

	primoPosizionamento : function(event)
	{
		clearInterval(this.interval);
		this.interval = '';

		if (event != undefined)
			this.posiziona(event);
		else
			this.posiziona(event);

		this.primoPosOk = true;

		this.tooltip.show();
		if (this.options.keepPosition)
			this.keepInterval = setInterval(this.eventKeepPosition,500);

		if (this.options.debug)
			console.log('primo posizionamento');
	},

	posiziona : function(event)
	{
		if ((this.options.debug) && (!$(this.tooltip)))
			console.log('no tooltip');

		if (!$(this.tooltip))
			return;
		if (!this.options.setStyle)
			return;

		// Ottengo la posizione
		var x = 0;
		var y = 0;
		if (event != undefined)
		{
			x = Event.pointerX(event);
			y = Event.pointerY(event);
			this.old.x = x;
			this.old.y = y;
		}
		else
		{
			x = this.old.x;
			y = this.old.y;
		}

		// Scroll della pagina
		var scroll = document.viewport.getScrollOffsets();
		// Dimensioni del tooltip
		var dim = this.tooltip.getDimensions();

		// Dimensioni della pagina
		var winHeigh = 0;
		if (navigator.appVersion.indexOf('MSIE')>0)
			winHeigh = document.body.clientHeight;
		else
			winHeigh = window.innerHeight;

		var winWidth = 0;
		if (navigator.appVersion.indexOf('MSIE')>0)
			winWidth = document.body.clientWidth;
    else
			winWidth = window.innerWidth;


		if (this.options.centrato)
		{
			// Lo posiziono al centro
			x = winWidth/2 - dim.width/2 + scroll.left;
			y = winHeigh/2 - dim.height/2 + scroll.top;
		}
		else if (this.options.hook != '')
		{
			//var offset = this.options.hook.obj.viewportOffset();
			var offset = this.options.hook.obj.cumulativeOffset();
			var dim = this.options.hook.obj.getDimensions();
			if (this.options.hook.type == 'bot-rig')
			{
				x = offset.left+dim.width;
				y = offset.top+dim.height;
			}
			else if (this.options.hook.type == 'bot-left')
			{
				x = offset.left;
				y = offset.top+dim.height;
			}
			else if (this.options.hook.type == 'top-rig')
			{
				x = offset.left+dim.width;
				y = offset.top;
			}
			else if (this.options.hook.type == 'top-left')
			{
				x = offset.left;
				y = offset.top;
			}

			x += this.options.hook.left;
			y += this.options.hook.top;
		}
		else if (this.options.fix_x != '')
		{
			x = this.options.fix_x;
			y = this.options.fix_y;
		}
		else
		{
			// Faccio finta che non esista lo scroll, questo semplifica i calcoli e la leggibilità
			x -= scroll.left;
			y -= scroll.top;

			var newY = 0;
			var newX = 0;
			var xOk = true;
			var yOk = true;

			if ((x+dim.width+this.options.delta_x) > winWidth)
			{
				// Troppo largo, Vedo se posso ribaltarlo altrimenti lo posiziono come posso
				if ((x-dim.width-this.options.delta_x) > 0)
					newX = x-dim.width-this.options.delta_x;
				else
				{
					// Segnalo che non sono riuscito a posizionare la X, dopo vedo se posso fare qualcosa
					xOk = false;
					newX = x+this.options.delta_x;
				}
			}
			else
				newX = x+this.options.delta_x;

			if ((y+dim.height+this.options.delta_y) > winHeigh)
			{
				// Troppo alto, Vedo se posso ribaltarlo altrimenti lo posiziono come posso
				if ((y-dim.height-this.options.delta_y) > 0)
					newY = y-dim.height-this.options.delta_y;
				else
				{
					// Visto che è sfalzato sulla x, sulla Y posso permettermi di passare "sopra" al cursorse
					newY = winHeigh-dim.height;
					yOk = false;
				}
			}
			else
				newY = y+this.options.delta_y;

			// Se non sono riuscito a posizionare la X, ma la Y è ok, posso posizionare la X in modo che superi il cursorse
			// Se la Y non fosse ok, allora avrei che vado sopra al mouse, condizione da evitare
			if ((!xOk) && (yOk))
				newX -= (x+dim.width+this.options.delta_x) - winWidth;

			// Faccio ricomparire lo scroll della pagina,altrimenti posizionerei come se fossi ancora in alto
			x = newX + scroll.left;
			y = newY + scroll.top;
		}

		if (this.options.debug)
			console.log('x:'+x+' y:'+y);

		// Imposto la nuova posizione
		this.setStyles(x, y);
	},

  showTooltip : function(event,click)
	{
		Event.stop(event);

		if (this.callback.mouseIn)
			this.callback.mouseIn();

		if (this.options.debug)
			console.log('mouse in');

		this.inTooltip = true;
		if (!this.inizializzato)
		{
			if (this.options.debug)
				console.log('non inizializzato');

			this.inizializza();
			this.inizializzato = true;

			// Sposto il tooltip fuori zona
			this.setStyles(-9999,-9999);
			// Mostro il tooltip
			this.tooltip.show();

			if (this.options.debug)
				console.log('show fuori limite');

			// Lo riposiziono dopo 1 po, altrimenti getDimensions da 1 valore errato e quindi lo posiziona male
			ritShow = this.options.showAfter;
			if ((ritShow == 0) || (click))
				ritShow = 50;
			clearInterval(this.interval);
      this.interval = setInterval(this.primoPosizionamento.bind(this,event), ritShow);

			// Se devo nasconderlo dopo 1 tot, allora registro quegli eventi
			if (this.options.hideAfter > 0)
				this.registerInactivity();

		}
		else if ((!this.primoPosOk) && (click))
		{
			if (this.options.debug)
				console.log('show click');

			// Se premo prima che il tempo sia scaduto, anticipo il tempo
			this.primoPosizionamento(event);
		}
		else if (this.primoPosOk)
		{
			if (this.options.debug)
				console.log('show primo ok');

			if (this.inactivity != '')
			{
				clearInterval(this.inactivity);
				this.tooltip.show();
				return;
			}

			// Posiziono
			this.posiziona(event);

			// Se lo posso mostrare subito provvedo, altrimenti lo mostro dopo 1 certo tempo
			if ((this.options.showAfter == 0) || (click))
			{
				this.tooltip.show();
				if (this.options.keepPosition)
					this.keepInterval = setInterval(this.eventKeepPosition,500);
			}
			else
			{
				this.mostra = true;
				clearInterval(this.activity);
				this.activity = setInterval(this.eventDelayedShow.bind(this,event), this.options.showAfter);
			}
		}
		else
		{
			if (this.options.debug)
				console.log('show.. non esistente');
		}
  },

	delayedShow : function()
	{
		clearInterval(this.activity);
		this.activity = '';

		// Mostro il tooltip
		this.tooltip.show();
	},

	stopInactivity : function()
	{
		clearInterval(this.inactivity);
		this.inactivity = '';
	},

	startInactivity : function()
	{
		if ((this.inToooltip) || (this.inLink))
			return;

		clearInterval(this.inactivity);
		this.inactivity = setInterval(this.eventEndInactivity, this.options.hideAfter);
	},
	endInactivity : function()
	{
		this.stopInactivity();

		// Qualche baco o qualche evento sfuggito
		if ((this.inToooltip) || (this.inLink))
			return;

		// Nascondo ( sono uscito dall'area di attivazione per 1 certo tempo )
		if ($(this.tooltip))
		{
			clearInterval(this.keepInterval);
			$(this.tooltip).hide();
		}

		if (this.callback.mouseOut)
			this.callback.mouseOut();
	},
	registerInactivity : function()
	{
		Event.observe(this.tooltip, "mouseover", this.eventMouseTipOver);
		Event.observe(this.tooltip, "mouseout", this.eventMouseTipOut);
	},
	tooltipOver : function()
	{
		this.inTooltip = true;
		this.stopInactivity();
	},
	tooltipOut : function()
	{
		this.inTooltip = false;
		this.startInactivity();
	},

	inizializza : function()
	{
		// ottengo l'elemento dall'id
		// se manca creo 1 tooltip vuoto
		if ($(this.tooltip))
		{
			this.tooltip = $(this.tooltip);
			if (this.options.defautlClass != '')
				this.tooltip.addClassName(this.options.defaultClass);

			// Setto il posizionamento assoluto e lo z-index
			if (this.options.setStyle)
			{
				Element.setStyle(this.tooltip,
					{ position:'absolute',
						zIndex:this.options.zIndex
					});
			}
		}
		else
			this.tooltip = this.creaDiv(this.tooltip);
	},

	creaDiv : function(testo)
	{
		// Il tooltip è un nuovo div che ho appena creato
		this.tooltip = new Element('div');

		if (this.options.ajaxUrl != '')
		{
			if (this.debug)
				console.log('ajaxtip');
			this.ajaxUpdate(this.options.ajaxUrl);
		}
		else
			this.tooltip.update(testo);
		// Verifico se ho un class di default da aggiungere
		if (this.options.defautlClass != '')
			this.tooltip.addClassName(this.options.defaultClass);

		// Inserisco il div nella pagina
		$(document.body).insert(this.tooltip);

		// Setto il posizionamento assoluto e lo z-index
		if (this.options.setStyle)
		{
			Element.setStyle(this.tooltip,
			{ position:'absolute',
				zIndex:this.options.zIndex
	 		});
		}


		return this.tooltip;
	},

	ajaxUpdate: function(url,callBack)
	{
		this.tooltip.innerHTML = '';
		this.tooltip.appendChild(this.getLoader());
		this.primoPosizionamento();

		var tooltip = this.tooltip;
		var thisTip = this;
		new Ajax.Request(url,
		{
			onSuccess: function(transport)
			{
				tooltip.innerHTML = transport.responseText;
				clearInterval(thisTip.interval);
				if (thisTip.debug)
					console.log('ajax : riattivo il primo posizionamento');
				if (tooltip.visible())
					thisTip.primoPosizionamento();
				if (callBack)
					callBack(tooltip);
				else if (thisTip.options.onAjaxComplete)
					thisTip.options.onAjaxComplete();
			},
			asynchronous:true
		});
	},

  setStyles : function(x, y)
	{
		if (!this.options.setStyle)
			return;

    // Setto la posizione
		Element.setStyle(this.tooltip,{ top:y + "px",	left:x + "px" });
  },

  hideTooltip : function()
	{
		// Se dovevo mostrarlo dopo 1 tot, è meglio che lo uccida subito sul nascere
		if (this.options.showAfter > 0)
		{
			clearInterval(this.activity);
			this.activity = '';
			this.mostra = false;
		}

		clearInterval(this.interval);

		this.interval = '';
		this.primoPosOk = true;

		// Se non deve chiudersi subito, allora setto solo che sono uscito dal tip
		if (this.options.hideAfter > 0)
		{
			this.inLink = false;
			this.startInactivity();
			return;
		}

		// Nascondo ( sono uscito dall'area di attivazione )
		if ($(this.tooltip))
		{
			clearInterval(this.keepInterval);
			$(this.tooltip).hide();
		}

		if (this.callback.mouseOut)
			this.callback.mouseOut();
  },

	updateContent: function(text)
	{
		if ($(this.tooltip))
			$(this.tooltip).update(text);
	},

	addCallBack: function(funct,metodo)
  {
    this.callback[metodo] = funct;
  },

	isVisible: function()
	{
		if (!$(this.tooltip))
			return false;
		if ($(this.tooltip).visible())
			return true;
		return false;
	}
};

ToolTip.Ajax = Class.create(ToolTip.Base,
{
	initialize: function($super,link,path,options)
	{
		var options = Object.extend({}, options || {});
		options.ajaxUrl = path;
		$super(link,'',options);
	}
});
ToolTip.ImageLoader = Class.create(ToolTip.Base,
{
	initialize: function($super,link,path,options)
	{
		var options = Object.extend({}, options || {});
		this.path = path;

		$super(link,'',options);
	},

	inizializza: function(event)
	{
		// Creo il div
		this.creaDiv(this.options.ajaxLoader);

		// Salvo in 1 variabile "locale" altrimenti la request non riesce a capire cosa aggiornare
		var tooltip = this.tooltip;

		// A questo punto scarico l'immagine
		var image = document.createElement('img');
		image.src = this.path;

		Event.observe(image, "load",
		function (e)
		{
			tooltip.update('');
			tooltip.appendChild(image);
		});
  }
});

ToolTip.Text = Class.create(ToolTip.Base,
{
	initialize: function($super,link,testo,options)
	{
		this.testo = testo;
		$super(link,'',options);
	},

	inizializza: function()
	{
		this.creaDiv(this.testo);
		// Setto il posizionamento assoluto e lo z-index
		if (this.options.setStyle)
		{
			Element.setStyle(this.tooltip,
				{ position:'absolute',
					zIndex:this.options.zIndex
				});
		}
  }
});

ToolTip.Alert = Class.create(ToolTip.Base,
{
	initialize: function($super,link,testo,options)
	{
		var options = Object.extend(
		{
			defaultClass: 'alert',
			centrato: true,
			incapsula: true,
			overlay:
			{
				opacity:0.6
			}
		}, options || {});

		this.testo = testo;
		$super(link,'',options);
	},

	registerEvents: function()
	{
		// Registro i vari eventi
		if (this.link)
		{
			if (this.options.rightClick)
				Event.observe(this.link, "contextmenu", this.eventMouseOver);
			else
				Event.observe(this.link, "click", this.eventMouseOver);
		}
  },

  destroy: function()
	{
		// Tolgo gli osservatori sui vari eventi
		if (this.link)
		{
			if (this.options.rightClick)
				Event.stopObserving(this.link, "contextmenu", this.eventMouseOver);
			else
				Event.stopObserving(this.link, "click", this.eventMouseOver);
		}

		Event.stopObserving(document, "click", this.eventMouseOut);
  },

  inizializza: function()
	{
		if (this.options.incapsula)
		{
			// Creo un div vuoto, poi ci inserisco il contenuto dopo con i pulsanti per chiudere etc
			this.creaDiv('');

			// Creo i 3 div head,centro,foot
			var divHead = new Element('div',{'id':'alertHead'});
			var divCent = new Element('div',{'id':'alertCent'});
			// Li inserisco all'interno del tooltip
			this.tooltip.insert(divHead);
			this.tooltip.insert(divCent);

			// Popoolo l'header
			var imgClose = new Element('img',{src:'image/delete.png'});
			$(divHead).insert(imgClose);

			Event.observe(imgClose, "click", this.eventMouseOut);

			// Popolo la parte centrale con il testo che mi è stato passato
			divCent.innerHTML = this.testo;
		}
		else
			this.creaDiv(this.testo);
  },

	showTooltip: function(event)
	{
		Event.stop(event);

		if ((ToolTip.Overlay.isLoaded) && (ToolTip.Overlay.caller != this))
		{
			// Se era già aperto e non sono stato io ad aprirlo
			// Chiudo il tooltip che l'ha aperto
			ToolTip.Overlay.caller.hideTooltip();
		}

		if (!this.inizializzato)
		{
			this.inizializza();
			this.inizializzato = true;
		}

		// Mostro l'overlay
		ToolTip.Overlay.show(this,this.options.overlay);

		// Mostro il tooltip
		this.tooltip.show();
		// Posiziono
		this.posiziona(event);

		if (this.options.overlay.opacity > 0)
		{
			// Registro l'evento che quando viene cliccato da qualche parte, allora deve far scomparire l'alert
			Event.observe(ToolTip.Overlay.overlay, "click", this.eventMouseOut);
		}
		else
		{
			// Registro l'evento che quando viene cliccato da qualche parte, allora deve far scomparire l'alert
			Event.observe(document, "click", this.eventMouseOut);
		}
  },

  hideTooltip: function(event)
	{
		// Nascondo
		this.tooltip.hide();
		// Segno che non devo più attendere 1 click sul document
		Event.stopObserving(document, "click", this.eventMouseOut);

		ToolTip.Overlay.hide();
  }

});
ToolTip.Persistent = Class.create(ToolTip.Alert,
{
	initialize: function($super,link,testo,options)
	{
		var options = Object.extend(
		{
			defaultClass: 'tooltip',
			centrato: false,
			incapsula: true,
			overlay: {	opacity:0 }
		}, options || {});

		$super(link,testo,options);
	}
});
ToolTip.Message = Class.create(ToolTip.Alert,
{
	initialize: function($super,testo,options)
	{
		var options = Object.extend(
		{
			defaultClass: 'tooltip',
			centrato: true,
			incapsula: true,
			overlay: {	opacity:0 }
		}, options || {});

		$super(null,testo,options);
	},

	showTooltip: function(event)
	{
		if (event != undefined)
			Event.stop(event);

		if ((ToolTip.Overlay.isLoaded) && (ToolTip.Overlay.caller != this) && (ToolTip.Overlay.caller != null))
		{
			// Se era già aperto e non sono stato io ad aprirlo
			// Chiudo il tooltip che l'ha aperto
			ToolTip.Overlay.caller.hideTooltip();
		}

		if (!this.inizializzato)
		{
			this.inizializza();
			this.inizializzato = true;
		}

		// Mostro l'overlay
		ToolTip.Overlay.show(this,this.options.overlay);

		// Mostro il tooltip
		this.tooltip.show();
		// Posiziono
		this.posiziona(event);

		if (this.options.overlay.opacity > 0)
		{
			// Registro l'evento che quando viene cliccato da qualche parte, allora deve far scomparire l'alert
			Event.observe(ToolTip.Overlay.overlay, "click", this.eventMouseOut);
		}
		else
		{
			// Registro l'evento che quando viene cliccato da qualche parte, allora deve far scomparire l'alert
			Event.observe(document, "click", this.eventMouseOut);
		}
		return false;
  },

	registerEvents: function()
	{
		// Non registro nessun evento, non serve

		// Mostro subito il tooltip
		this.showTooltip();
  },

  hideTooltip: function(event)
	{
		// Nascondo
		this.tooltip.hide();
		// Segno che non devo più attendere 1 click sul document
		Event.stopObserving(document, "click", this.eventMouseOut);

		ToolTip.Overlay.hide();

		this.destroy();
  },

  destroy : function()
	{
		// Se ho creato il div, lo elimino
		if (this.tooltip)
			this.tooltip.parentNode.removeChild(this.tooltip);
  }
});

ToolTip.Overlay =
{
	isLoaded: false,
	inizializzato: false,
	overlay:null,
	caller:null,

	inizializza: function()
	{
		this.inizializzato = true;
		// L'overlay è un nuovo div che ho appena creato
		this.overlay = new Element('div');
		// Inserisco il div nella pagina
		$(document.body).insert(this.overlay);
	},
	show: function(caller,options)
	{
		var options = Object.extend(
		{
			style:
			{
				position: 'fixed',
				top: 0,
				left: 0,
				width: '100%',
				height: '100%',
				zIndex: 998,
				'background':'#000'
			},
			opacity:0.6
		}, options || {});

		if (!this.inizializzato)
			this.inizializza();
		this.isLoaded = true;
		if (options.opacity > 0)
		{
			this.overlay.setOpacity(options.opacity);
			this.overlay.show();
			Element.setStyle(this.overlay,options.style);
		}
		this.caller = caller;
	},
	hide: function()
	{
		this.isLoaded = false;
		this.overlay.hide();
		this.caller = null;
	}

}

