var Overlay = function (className, properties) {
	// Caratteristiche overlay	
	this.id = className + Math.floor(Math.random() * 100);
	this.YUIoverlay = new YAHOO.widget.Panel(this.id, properties);
	
	// Stabilisce per quanto tempo resta visibile la finestra prima di essere chiusa
	this.visibleFor = 0;
	
	// Timeout apertura/chiusura
	this.showTimeout = null;
	this.hideTimeout = null;

	// Effetti
	this.showEffect = null;
	this.hideEffect = null;
	
	// Ancoraggio
	this.corner = {	overlay: null,
					context: null
	};
	
	// Chiamata Ajax
	this.scriptUrl = "";
	
	// Metodo di connessione
	this.connectionMethod = 'POST';
	
	// Identifica un overlay a più passi
	this.stepOverlay = false;
	
	// Se true nasconde il terzo passo della finestra
	this.hideAfterLoad = false;
	
	// Se true vengono visualizzati i messaggi nella console (funziona solo con Firefox)
	this.debugMode = false;
	
	// Contenuto della finestra per il loading
	this.loaderContent = {	header: '',
							body: '<div id="oLoader" class="loader"></div>',
							footer: ''
	};
	
	// Colore overlay da prendere al momento
	this.color = 'blu';
	
	// Colore di default overlay
	this.defaultColor = 'blu';
	
	// Colore overlay di errore
	this.errorColor = 'rosso';
	
	// Messaggio di errore generico
	this.defaultErrorMessage = 'Oops! Qualcosa è andato storto, riprova più tardi!';
	
	// Stabilisce se debba o meno centrare l'overlay
	this.center = true;
	
	// Classi addizionali per l'overlay
	this.cssClasses = new Array(className);
	
	this.addClass = function (className) {
		this.cssClasses.push(className);
	};
	
	// Imposta la classe per lo stile dell'overlay
	this._setClasses = function () {
		var overlay = YAHOO.util.Dom.get(this.YUIoverlay.id);
		YAHOO.util.Dom.addClass(overlay, className);
		
		for(var i in this.cssClasses)
			YAHOO.util.Dom.addClass(overlay, this.cssClasses[i]);
	};
	
	// Registra le modalità di apertura e chiusura dell'overlay
	this.registerTransitions = function (anchorShow, content, anchorHideId) {
		this.registerShow(anchorShow, content, anchorHideId);
		// if(this.debug) console.log("Overlay >> registerTransitions: transizioni registrate, l'overlay è agganciato a '" + (anchorShow.id ? anchorShow.id : anchorShow) + "'");		
	};
	
	// Registra le modalità per l'apertura dell'overlay
	this.registerShow = function (anchor, content, anchorHideId) {
		var me = this;

		YAHOO.util.Event.on(anchor, this.showEffect.on, function() {
			this.showTimeout = window.setTimeout(function () {
				me.show(anchor, content, anchorHideId);
												
			}, me.showEffect.delay * 1000);
			
			if(this.debug) console.log("Overlay >> registerShow: scattato evento '" + this.showEffect.on + "' su '" + anchor.id + "'");
		});
		
		// if(this.debug) console.log("Overlay >> registerShow: transizione show registrata per l'oggetto '" + (anchor.id ? anchor.id : anchor) + "'");
	};
	
	// Registra le modalità per la chiusura dell'overlay
	this.registerHide = function (anchorID) {
		var me = this;

		// Chiusura temporizzata
		if(this.visibleFor > 0 && !this.stepOverlay)
			this.registerTimedHide();
			
		// Chiusura in seguito ad un evento
		else if(this.hideEffect)
			YAHOO.util.Event.on(YAHOO.util.Dom.get(anchorID), this.hideEffect.on, function() {
				if(this.hideTimeout) clearTimeout(this.hideTimeout);
				this.hideTimeout = window.setTimeout(function () {
					me.hide();
				}, me.hideEffect.delay * 1000);
			});
		
		// if(this.debug) console.log("Overlay >> registerHide: transizione hide registrata per l'oggetto '" + anchorID + "'");
	};

	// Registra la chiusura automatica temporizzata
	this.registerTimedHide = function () {
		var me = this;
		
		if(this.hideTimeout) clearTimeout(this.hideTimeout);
		this.hideTimeout = window.setTimeout(function () {
			me.hide();
		}, me.visibleFor * 1000);
	};
	
	// Mostra l'overlay
	this.show = function (anchorShow, content, anchorHideId) {
		if(content) this.setContent(content.header, content.body, content.footer);
		
		this.YUIoverlay.render(document.body);
		this._setClasses();
		
		if(anchorShow) this.setPosition(anchorShow);
		this.YUIoverlay.show();
		
		this.registerHide(anchorHideId);
		
		// Centra l'overlay
		if(this.center) this.centerOverlay();
		
		// if(this.debug && anchorShow) console.log("Overlay >> show: overlay ancorato all'oggetto '" + (anchorShow.id ? anchorShow.id : anchorShow) + "' è stato reso visibile");
	};
	
	this.centerOverlay = function () {
		window.scrollTo(0, 1);
		window.scrollTo(0, 0);
	};
	
	// Nasconde l'overlay
	this.hide = function () {
		this.YUIoverlay.hide();
	};
	
	// Funzione da eseguire alla chiusura dell'overlay
	this.onClose = function (fn) {
		this.YUIoverlay.hideEvent.subscribe(fn);
	};
	
	// Funzione da eseguire all'apertura dell'overlay
	this.onShow = function (fn) {
		this.YUIoverlay.showEvent.subscribe(fn);
	};
	
	// Imposta il contenuto dell'overlay
	this.setContent = function (header, body, footer) {
		this.YUIoverlay.setHeader(header);
		this.YUIoverlay.setBody(body);
		this.YUIoverlay.setFooter(footer);
		
		// if(this.debug) console.log("Overlay >> setContent: contenuto overlay impostato");
	};
	
	// Imposta la posizione dell'overlay rispetto all'oggetto a cui è ancorato
	this.setPosition = function (anchor) {
		this.YUIoverlay.cfg.setProperty("context", [anchor, this.corner.overlay, this.corner.context]);
	};
	
	// Wrapper per getContentByAjax
	this.ajaxCall = function (actionString, anchorShow, anchorHideId, obj, secondStep) {
		this.getContentByAjax(actionString, anchorShow, anchorHideId, obj, secondStep);
	};
	
	// Ottiene il contenuto di un overlay tramite uan chiamata AJAX
	this.getContentByAjax = function (actionString, anchorShow, anchorHideId, obj, formName, secondStep) {
		this.color = this.defaultColor;
		var me = this;
		
		var callback = {
		    success: function (o) {
				me._manageSuccessContent(o.responseText, anchorShow, anchorHideId, obj, secondStep);
		    },
		    upload: function (o) {
		    	me._manageSuccessContent(o.responseText, anchorShow, anchorHideId, obj, secondStep);
		    },
		    failure: function (o) {
		    	obj.overlay.color = obj.overlay.errorColor;
		    	me._manageResult(obj, anchorShow, obj.overlay.defaultErrorMessage, anchorHideId, secondStep);
		    }
		};

		if(formName) YAHOO.util.Connect.setForm(formName, true, true);
		var conn = this._connect(actionString, callback);
		obj.show(null, this.loaderContent.body, null);
	};
	
	this._manageSuccessContent = function (responseText, anchorShow, anchorHideId, obj, secondStep) {
		var pResponse = this._parseResult(responseText);
		
		if(Utilities.isArray(pResponse)) {
			this._manageResponse(pResponse[0], obj);
			pResponse = pResponse[1];
		} else if(pResponse.result) {
			this._manageResponse(pResponse, obj);
			if(pResponse.result == 'LP') return;
		}
		
		this._manageResult(obj, anchorShow, pResponse, anchorHideId, secondStep);
	};
	
	this._manageResponse = function (pResponse, obj) {
		if(pResponse.result == 'LP') {
			obj.overlay.hide();
			OverlayManager.show('lp', pResponse.lp, pResponse.enc_profile_id);
			return;
		}
	};
	
	this._parseResult = function (response) {
		return Utilities.parseHybridResponse(response);
	};
	
	// Come getContentByAjax ma ottiene una risposta ad un'azione anzichè il contenuto dell'overlay
	this.getResultByAjax = function (actionString, obj, fn, formName) {
		this.color = this.defaultColor;
		var me = this;
		
		var callback = {
		    success: function (o) {			
				me._manageSuccessResult(o.responseText, obj, fn);
		    },
		    upload: function (o) {
		    	me._manageSuccessResult(o.responseText, obj, fn);
		    },
		    failure: function (o) {
		    	obj.overlay.color = obj.overlay.errorColor;
		    	fn(obj, this._createErrorStruct(this.defaultErrorMessage));
		    }
		};

		if(formName) YAHOO.util.Connect.setForm(formName, true, true);
		var conn = this._connect(actionString, callback);
		obj.show(null, this.loaderContent.body, null);
	};
	
	this._manageSuccessResult = function (responseText, obj, fn) {
		try {
			var response = YAHOO.lang.JSON.parse(responseText);
					
			if(Utilities.needLP(responseText, true)) {
				obj.overlay.hide();
				Utilities.checkFeature(responseText, true);
			}
			else fn(obj, response);
		} catch (e) {
			obj.overlay.color = obj.overlay.errorColor;
			fn(obj, this._createErrorStruct(this.defaultErrorMessage));
		}
	};
	
	this._createErrorStruct = function (errorMessage) {
		return {
			result: 'KO',
			header: '',
			body: errorMessage,
			footer: '',
			params: { }
		};
	};
	
	// Esegue la chiamata AJAX
	this._connect = function (actionString, callback) {
		return (this.connectionMethod == 'POST') ?
	    		YAHOO.util.Connect.asyncRequest('POST', this.scriptUrl, callback, actionString) :
	    		YAHOO.util.Connect.asyncRequest('GET', this.scriptUrl + "?" + actionString, callback);
	};
	
	// Gestisce il risultato ottenuto dalla chiamata
	this._manageResult = function (obj, anchorShow, responseText, anchorHideId, secondStep) {
		var text = ''; 
		
		try {
			var json = YAHOO.lang.JSON.parse(responseText);
			text = json.body;
		}
		catch (e) { text = responseText; }
		
		if(!obj.overlay.hideAfterLoad) obj.show(anchorShow, text, anchorHideId);
		else obj.overlay.overlay.hide();
		
		if(secondStep && !obj.overlay.hideAfterLoad && obj.overlay.visibleFor) { obj.overlay.registerTimedHide(); }
	};
	
	// Wrapper per setContentByAjax che rende le chiamate specifiche per gli overlay nel secondo passo
	this.stepTwo = function (actionString, anchorShow, anchorHideId, obj, formName) {
		this.setContentByAjax(actionString, anchorShow, anchorHideId, obj, formName, true);
	};
	
	// Imposta il contenuto di un'overlay tramite una chiamata AJAX
	this.setContentByAjax = function (actionString, anchorShow, anchorHideId, obj, formName, secondStep) {
		// obj.show(anchorShow, this.loaderContent.body, anchorHideId);
		this.getContentByAjax(actionString, anchorShow, anchorHideId, obj, formName, secondStep);
	};
	
	// Restituisce true se esiste la console ed è stata impostata la modalità debug
	this.debug = function () {
		return window.console && this.debugMode;
	};
	
	// Genera la grafica di un overlay. Il secondo parametro è opzionale	
	this.generateOverlay = function (text) {
		return { header: '<span class="o-tLeft"></span><span class="o-tRight"></span><span class="o-bLeft"></span><span class="o-bRight"></span>',
				body: '<div class="' + this.color + '">' +
					'<span class="tLeft"></span>' +
					'<span class="tRight"></span>' +
					'<span class="bLeft"></span>' +
					'<span class="bRight"></span>' +
					'<div class="box">' +
						text +
					'</div>' +
				'</div>',
				footer: ''
		};
	};
	
	this.isSuccessResponse = function (response) {
		return response == 'OK' || response == 'LP';
	};
};