MOWSlide = Class.create();
MOWSlide.prototype = {

	initialize: function(MOWSlideDiv, MOWSlideDefinition) {

		// Eventuali altri parametri
		this.pars = $H({
			PositionHReference:			'center',
			PositionVReference:			'top',
			AutoStart:					true,
			CreateInAbsoluteDiv:		false,
			CreateAtPageBottom:			false,
			onStart:					null,	
			onStop:						null,	
			Debug:						false,
			PrefetchSeconds:			4,
			ForcePosition:				{}
		});
		this.pars = this.pars.merge($H(arguments[2] || {}));

		this.Name = this.RandomID();
		eval(this.Name+'=this');

		this.doDebug = false;
		this.DebugLayer = null;
		
	
		// Div dove creare l'MOWSlide
		this.PlaceHolderDivID 	= MOWSlideDiv;
		if (MOWSlideDefinition) {
			this.SlideDefinition = MOWSlideDefinition;
		} 
		//else {
		//	this.SlideDefinition = MOWSlideDemoDefinition;
		//}		
		
		// Stato dell' MOWSlide
		this.isPlaying 				= false;
		this.couldStart				= false;
		this.onStartAlreadyExecuted = false;

		this.currentSecondArray		= new Array();
		this.currentSecondArray[0]	= 0;
		this.totalSecondsArray		= new Array();
		this.totalSecondsArray[0]	= 0;
		this.howManyTimes			= new Array();
		this.howManyTimes[0]		= 0;
		this.SequenceArray			= new Array();
		this.ObjectsArray			= new Array();
		this.currentArrayLevel		= 0;
		this.StopOnce				= false;

		// Creo ed inizializzo il contenitore
		this.holderDiv = null;
		
		this.InstantHolder = null;
		this.InstantMode = false;
		this.InstantModeArrayLevel = 0;		
		
		this.Objects = new Array();
		this.ObjectMorphEffect = new Array();
		
		Event.observe(window, 'load', this.onWindowLoad.bindAsEventListener(this)); 
		
	},
	
	onWindowLoad: function() {
		this.PlaceHolderDiv		= $(this.PlaceHolderDivID);
		this.width				= this.PlaceHolderDiv.getWidth();
		this.height				= this.PlaceHolderDiv.getHeight();	
		this.holderDiv 			= this.pars.get('CreateInAbsoluteDiv') ? this.createInAbsoluteDiv() : this.createHolder();
		this.ObjectsDefs 		= $H(this.SlideDefinition.Objects);
		this.SequenceArray[0] 	= $H(this.SlideDefinition.MainSequence);
		
		this.handleSequenceBeginning();
		
		this.couldStart			= true;
		
		if (this.pars.get('Debug'))
			this.enableDebug();		
		
		if (this.pars.get('AutoStart'))
			this.start();		
	},
	
	enableDebug: function() {
		this.DebugLayer = new Element('div', {style:'position:absolute;overflow-y:auto;top:0px;left:0px;height:600px;width:300px;display:none;background-color:#000;color:#FFF;'});
		Play = new Element('div', {style:'padding:4px;position:absolute;top:10px;left:310px;height:30;width:80px;display:none;background-color:#000;color:#FFF;', onClick:this.Name+'.start();'});
		Stop = new Element('div', {style:'padding:4px;position:absolute;top:50px;left:310px;height:30;width:80px;display:none;background-color:#000;color:#FFF;', onClick:this.Name+'.stop();'});
		new Element.insert(this.holderDiv, {after: this.DebugLayer}); this.DebugLayer.innerHTML = '<b>MOWSLide::DebugMode</b><br />'; new Effect.Appear(this.DebugLayer, {from:0.0, to:0.7, duration:1});		
		new Element.insert(this.holderDiv, {after: Play}); Play.innerHTML = 'Play'; new Effect.Appear(Play, {from:0.0, to:0.7, duration:1});		
		new Element.insert(this.holderDiv, {after: Stop}); Stop.innerHTML = 'Stop'; new Effect.Appear(Stop, {from:0.0, to:0.7, duration:1});		
		this.doDebug = true;
		PositionInfo = this.findRealPosition(this.PlaceHolderDiv);
		this.debug('Posizione Holder - left: '+ PositionInfo['x']+'px, top: '+PositionInfo['y']+'px, width: '+this.width+'px, height: '+this.height+'px');
	},
	
	debug: function(text) {
		if (this.doDebug)
			this.DebugLayer.innerHTML += text;
	},

	/**
	*	Crea il contenitore x le slide, in posizione assoluta e fissa rispetto alla pagina, clonando la posizione e dimensione del
	*	div contenitore delle slide.
	*/ 
	createHolder: function() {
		//this.PlaceHolderDiv.innerHTML = '';
		PositionInfo = this.findRealPosition(this.PlaceHolderDiv);
		Position = {position: 'absolute', left: PositionInfo['x']+'px', top: PositionInfo['y']+'px', width: this.width+'px', height: this.height+'px'};
		
		
		// Cambia il posizionamento da assoluto a "centrato" orizzontalmente
		if (this.pars.get('PositionHReference') == 'center') {
			DocumentWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth;
			Position.left = '50%';
			Position.marginLeft = (PositionInfo['x'] - DocumentWidth/2)+'px';
		}
		// Cambia il posizionamento da assoluto a "centrato" verticalmente
		if (this.pars.get('PositionVReference') == 'center') {
			DocumentHeight = document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
			Position.top = '50%';
			Position.marginTop = (PositionInfo['y'] - DocumentHeight/2)+'px';
		}
		
		// Forzature da parametri
		if (this.pars.get('ForcePosition')) {
			Position = Object.extend(Position, this.pars.get('ForcePosition'));
		}
		
		aHolderDiv = new Element('div', {style:'position:absolute;overflow:hidden;'});
		aHolderDiv.setStyle(Position);

		if (this.pars.get('keepOver')) {
			this.keepOver(this.pars.get('keepOver'));
		}

		if (this.holderDiv) {
			new Element.insert(this.holderDiv, {after: aHolderDiv});
		} else {
			if(this.pars.get('CreateAtPageBottom')) {
				new Element.insert(window.document.body, {bottom: aHolderDiv});
			} else {
				new Element.insert(this.PlaceHolderDiv, {after: aHolderDiv});
			}
		}
		
		return aHolderDiv;
	},
	
	createInAbsoluteDiv: function() {
		aHolderDiv = new Element('div', {style:'position:absolute;overflow:hidden;top:0px;left:0px;width:100%;height:100%;'});
		new Element.insert(this.PlaceHolderDiv, {bottom: aHolderDiv});
		return aHolderDiv;
	},
	
	keepOver: function(Element) {
		Element = $(Element);
		PositionInfo = this.findRealPosition(Element);
		Position = {left: PositionInfo['x']+'px', top: PositionInfo['y']+'px', position: 'absolute'};

		// Cambia il posizionamento da assoluto a "centrato" orizzontalmente
		if (this.pars.get('PositionHReference') == 'center') {
			DocumentWidth = document.documentElement.clientWidth ? document.documentElement.clientWidth : document.body.clientWidth;
			Position.left = '50%';
			Position.marginLeft = (PositionInfo['x'] - DocumentWidth/2)+'px';
		}
		// Cambia il posizionamento da assoluto a "centrato" verticalmente
		if (this.pars.get('PositionVReference') == 'center') {
			DocumentHeight = document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
			Position.top = '50%';
			Position.marginTop = (PositionInfo['y'] - DocumentHeight/2)+'px';
		}


		//document.body.appendChild(Element);
		//new Element.insert(this.PlaceHolderDiv, {after: Element});
		new Insertion.After(this.PlaceHolderDiv, Element);

		$(Element).setStyle(Position);	
	},
	
	/**
	* Crea un singolo oggetto, si comporta diversamente a seconda del tipo
	*/
	createElement: function(ObjectHash) {
		var NewObject;
		switch (ObjectHash.get('type')) {
			// Se l'oggetto e' un'immagine si occupa di precaricala (invisibile)
			case 'image':
					NewObject = new MOWImage(ObjectHash.get('src'));
					if (ObjectHash.keys().indexOf('style') != -1) {
						Style = ObjectHash.get('style');
						if (Object.keys(Style).length > 0)
						NewObject.setStyle(Style);
					}
					break;
			
			case 'text':
					NewObject = new MOWText();
					if (ObjectHash.keys().indexOf('style') != -1) {
						Style = ObjectHash.get('style');
						if (Object.keys(Style).length > 0)
						NewObject.setStyle(Style);
					}
					if (ObjectHash.keys().indexOf('html') != -1) 
						NewObject.theObject.innerHTML = ObjectHash.get('html')
					if (ObjectHash.keys().indexOf('htmlFromID') != -1) 
						NewObject.theObject.innerHTML = $(ObjectHash.get('htmlFromID')).innerHTML;
				break;
		}
		
		return NewObject;
	},
	
	currentSecond: function(val) {
		if (typeof(val) != 'undefined') {
			this.currentSecondArray[this.currentArrayLevel] = val;
		}
		return this.currentSecondArray[this.currentArrayLevel];
	},
	
	currentHowManys: function(val) {
		if (typeof(val) != 'undefined') {
			this.howManyTimes[this.currentArrayLevel] = val;
		}
		return this.howManyTimes[this.currentArrayLevel];
	},

	totalSeconds: function(val) {
		if (typeof(val) != 'undefined') {
			this.totalSecondsArray[this.currentArrayLevel] = val;
		}
		return this.totalSecondsArray[this.currentArrayLevel];
	},
	
	currentSequence: function(val) {
		if (typeof(val) != 'undefined') {
			this.SequenceArray[this.currentArrayLevel] = val;
		}
		return this.SequenceArray[this.currentArrayLevel];
	},
	
	currentHolder: function() {
		if (this.InstantMode) {
			return this.InstantHolder;
		} else {
			return this.holderDiv;
		}
	},
	
	handleSequenceBeginning: function() {
		if (this.currentArrayLevel == 0 || (this.InstantMode && this.currentArrayLevel == this.InstantModeLevel)) {
			// Sto visualizzando la sequenza base
			this.currentSecond(0);
			this.totalSeconds(this.currentSequence().keys().last());
		} else {
			if (this.currentHowManys() == 0) {
				// Ho finito l'injection corrente, scendo di un livello
				this.currentArrayLevel--;
				this.currentSecond(this.currentSecond() + 1); 
				if (this.currentSecond() > this.totalSeconds())
					this.handleSequenceBeginning();
			} else {
				// Sono in un injection e ci rimango, ma acalo di uno la ripetizione corrente e la lancio
				this.currentSecond(0);
				this.totalSeconds(this.currentSequence().keys().last());
				this.currentHowManys(this.currentHowManys()-1);
				this.debug('Da ripetere: '+this.currentHowManys()+' volte<br />');
			}
		}
		this.debug('totalSeconds: '+this.totalSeconds()+'<br />');
	},
	
	/**
	* Avvia il funzionamento della slide:
	*/
	start: function() {
		if (!this.couldStart) return;
		// Crea tutti gli oggetti
		this.isPlaying = true;
		this.nextSecond();
		if (!this.onStartAlreadyExecuted && this.pars.get('onStart') != null) {
			this.onStartAlreadyExecuted = true;
			this.pars.get('onStart')();
		}
	},
	
	nextSecond: function(doNotStop) {
		if (this.StopOnce && typeof(doNotStop) != 'undefined') {
			// Se per caso e' stato impostato lo StopOnce (salta un nextSecond) 
			// perche' ne e' stato invocato un altro, allora salta
			this.StopOnce = false;
			return;
		}
	
		// Prefetch dei prossimi 4 secondi
		this.prefetchXSeconds(this.pars.get('PrefetchSeconds'));
		
		// Verifica se c'e' un'azione al secondo corrente
		if (this.currentSequence().get(this.currentSecond())) {
			// Esegui l'azione o le azioni
			theAction = this.currentSequence().get(this.currentSecond());

			// Verifica prima abbiamo finito di caricare gli oggetti, se no aspetta. (migliorabile)
			if (!this.checkIfObjectsAreLoaded(theAction)) {
				this.debug('Oggetti ancora in caricamento, aspetto<br />');
				if (this.isPlaying) setTimeout(this.Name+'.nextSecond()', 1000);
				return;
			}

			this.executeAction(theAction);
		}
	
		this.debug('currentSecond: '+this.currentSecond()+'<br />');
		
		// Avanza al secondo successivo, se sfora ricomincia.
		this.currentSecond(this.currentSecond() + 1); 
		if (this.currentSecond() > this.totalSeconds())
			this.handleSequenceBeginning();
		
		if (this.isPlaying) setTimeout(this.Name+'.nextSecond()', 1000);
	},
	
	checkIfObjectsAreLoaded: function(theAction) {
		// In caso di array di azioni le esegue tutte
		if (Object.isArray(theAction)) {
			result = true;
			for (i=0; i < theAction.length; i++) {
				result = result && this.checkIfObjectsAreLoaded(theAction[i]);
			}
			return result;
		} 

		// Se l'azione riguarda un oggetto (e non e' null ovvero un prefetch forzato)
		if (Object.keys(theAction).indexOf('obj') != -1 && theAction.action != 'null') {
			// nel dubbio verifica se l'oggetto e' creato, se no crealo
			this.prefetchSingleAction(theAction);
			
			// Se e' un immagine e non e' ancora caricata ritorna falso
			if (this.ObjectsDefs.get(theAction.obj).type=='image' && this.Objects[theAction.obj].isLoaded == false) 
				return false;
		}
		
		// Se siamo qua ok
		return true;
	},

	prefetchXSeconds: function(secondsFurther) {
		for (i=0; i < secondsFurther; i++) {
			secondToPrefetch = this.currentSecond() + i;
			
			// Verifica se esistono azioni in questo secondo
			if (this.currentSequence().get(secondToPrefetch)) {
				// Recupera la/le azioni
				theAction = this.currentSequence().get(secondToPrefetch);
				
				// Verifica se sono una o piu'
				if (Object.isArray(theAction)) {
					for (j=0; j < theAction.length; j++) {
						this.prefetchSingleAction(theAction[i]);
					}
				} else {
					this.prefetchSingleAction(theAction);
				}
			}
		}
	},
	
	prefetchSingleAction: function(theAction) {
		if (Object.keys(theAction).indexOf('obj') != -1) {
			// Verifica, se l'oggetto non esiste lo crea.
			if (!this.Objects[theAction.obj]) {
				this.debug('obj: '+theAction.obj+'<br />');
				this.Objects[theAction.obj] = this.createElement($H(this.ObjectsDefs.get(theAction.obj)));
				this.ObjectMorphEffect[theAction.obj] = null;
			}			
		}
	},
	
	cancelMorphEffect: function(objectName) {
		if (this.ObjectMorphEffect[objectName] != null) {
			this.ObjectMorphEffect[objectName].cancel();
			this.ObjectMorphEffect[objectName] = null;
		}
	},
	
	/**
	* Esegui un'azione
	*/
	executeAction: function(theAction) {
		// In caso di array di azioni le esegue tutte
		if (Object.isArray(theAction)) {
			for (i=0; i < theAction.length; i++) {
				this.executeAction(theAction[i]);
			}
			return;
		}
		
		// Esegui la singola azione
		switch (theAction.action) {
			case 'Morph':
					// Cancella l'eventuale effetto in corso
					this.cancelMorphEffect(theAction.obj);
					if (theAction.duration) 
						this.ObjectMorphEffect[theAction.obj] = new Effect.Morph(this.Objects[theAction.obj].theObject, {style: theAction.style, duration:theAction.duration});
					else 
						this.ObjectMorphEffect[theAction.obj] = new Effect.Morph(this.Objects[theAction.obj].theObject, {style: theAction.style});
					
					break;
					
			case 'SetInPosition':
					if (theAction.style) this.Objects[theAction.obj].setStyle(theAction.style);

					this.currentHolder().appendChild(this.Objects[theAction.obj].theObject);

					this.Objects[theAction.obj].setStyle({position:'absolute'});
					this.Objects[theAction.obj].setStyle({top:null, bottom:null, left:null, right:null});
					if (theAction.top) this.Objects[theAction.obj].setStyle({top:theAction.top});
					if (theAction.bottom) this.Objects[theAction.obj].setStyle({bottom:theAction.bottom});
					if (theAction.left) this.Objects[theAction.obj].setStyle({left:theAction.left});
					if (theAction.right) this.Objects[theAction.obj].setStyle({right:theAction.right});
					
					break;
		
			case 'AppearInPosition':
					this.Objects[theAction.obj].setStyle({display:'none'});
					if (theAction.style) this.Objects[theAction.obj].setStyle(theAction.style);

					this.currentHolder().appendChild(this.Objects[theAction.obj].theObject);

					this.Objects[theAction.obj].setStyle({position:'absolute'});
					
					this.Objects[theAction.obj].setStyle({top:null, bottom:null, left:null, right:null});
					
					if (theAction.top) this.Objects[theAction.obj].setStyle({top:theAction.top});
					if (theAction.bottom) this.Objects[theAction.obj].setStyle({bottom:theAction.bottom});
					if (theAction.left) this.Objects[theAction.obj].setStyle({left:theAction.left});
					if (theAction.right) this.Objects[theAction.obj].setStyle({right:theAction.right});
					
					
					if (theAction.duration) 
						new Effect.Appear(this.Objects[theAction.obj].theObject, {duration:theAction.duration});
					else 
						new Effect.Appear(this.Objects[theAction.obj].theObject);
						
					break;
					
			case 'FlashInPosition':
					this.Objects[theAction.obj].setStyle({display:'none'});
					this.currentHolder().appendChild(this.Objects[theAction.obj].theObject);
					this.Objects[theAction.obj].setStyle({position:'absolute'});
					
					this.Objects[theAction.obj].setStyle({top:null, bottom:null, left:null, right:null});
					
					if (theAction.top) this.Objects[theAction.obj].setStyle({top:theAction.top});
					if (theAction.bottom) this.Objects[theAction.obj].setStyle({bottom:theAction.bottom});
					if (theAction.left) this.Objects[theAction.obj].setStyle({left:theAction.left});
					if (theAction.right) this.Objects[theAction.obj].setStyle({right:theAction.right});
					
					FlashCover = new Element('div', {style:'position:absolute;top:0px;left:0px;width:100%;height:100%;background-color:#FFFFFF;'});
					this.currentHolder().appendChild(FlashCover);
					//Element.clonePosition(FlashCover, this.Objects[theAction.obj].theObject);
					FlashCover.show();
					this.Objects[theAction.obj].theObject.show()
					
					if (theAction.duration)
						new Effect.Fade(FlashCover, {duration:theAction.duration, onComplete:FlashCover.remove});
					else 
						new Effect.Fade(FlashCover, {onComplete:FlashCover.remove, duration:0.5});
					break;
					
			case 'Fade':
					if (theAction.duration)
						new Effect.Fade(this.Objects[theAction.obj].theObject, {duration:theAction.duration, onComplete:this.Objects[theAction.obj].theObject.remove});
					else 
						new Effect.Fade(this.Objects[theAction.obj].theObject, {onComplete:this.Objects[theAction.obj].theObject.remove});
					break;
					
			case 'Hide':
					this.Objects[theAction.obj].theObject.hide();
					break;
					
			case 'Highlight':
					if (theAction.duration)
						new Effect.Highlight(this.Objects[theAction.obj].theObject, {duration:theAction.duration});
					else 
						new Effect.Highlight(this.Objects[theAction.obj].theObject);
					break;
					
			case 'Pulsate':
					if (theAction.duration)
						new Effect.Pulsate(this.Objects[theAction.obj].theObject, {duration:theAction.duration});
					else 
						new Effect.Pulsate(this.Objects[theAction.obj].theObject);
					break;
					
			case 'Shake':
					if (theAction.duration)
						new Effect.Shake(this.Objects[theAction.obj].theObject, {duration:theAction.duration});
					else 
						new Effect.Shake(this.Objects[theAction.obj].theObject);
					break;
					
			case 'Effect':
					eval('new Effect.'+theAction.name+'(this.Objects[theAction.obj].theObject, theAction.parameters);');
					break;
					
			case 'ChangeHTML':
					if (theAction.style) 
						this.Objects[theAction.obj].setStyle(theAction.style);
					if (theAction.html) 
						this.Objects[theAction.obj].theObject.innerHTML = theAction.html
					if (theAction.htmlFromID) 
						this.Objects[theAction.obj].theObject.innerHTML = $(theAction.htmlFromID).innerHTML;
					break;
					
			case 'InjectSequence':
					this.currentArrayLevel++;
					this.currentSequence($H(eval('this.SlideDefinition.'+theAction.sequence)));
					this.currentHowManys(theAction.times);
					this.handleSequenceBeginning();
					this.currentSecond(-1);
					break;
					
			case 'ChangeSequence':
					//this.currentArrayLevel++;
					this.currentSequence($H(eval('this.SlideDefinition.'+theAction.sequence)));
					this.currentHowManys(0);
					this.handleSequenceBeginning();
					this.currentSecond(-1);
					//this.start();
					break;
					
			case 'ChangeSequenceNoStart':
					//this.currentArrayLevel++;
					this.currentSequence($H(eval('this.SlideDefinition.'+theAction.sequence)));
					this.currentHowManys(0);
					this.handleSequenceBeginning();
					this.currentSecond(-1);
					break;
					
			case 'InjectRandomSequence':
					this.currentArrayLevel++;
					RandomArray = eval('this.SlideDefinition.Objects.'+theAction.array);
					//alert(Object.inspect(RandomArray));
					//alert(Math.floor(Math.random() * RandomArray.length));
					this.currentSequence($H(eval('this.SlideDefinition.'+RandomArray[Math.floor(Math.random() * RandomArray.length)])));
					this.currentHowManys(theAction.times);
					this.handleSequenceBeginning();
					this.currentSecond(-1);
					break;
					
			case 'Stop':
					this.stop();
					break;
		}
	},

	stop: function() {
		this.isPlaying = false;

		if (this.pars.get('onStop') != null) {
			this.pars.get('onStop')();
		}
	},

	//--- Instant SLIDE -------------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------------------------

	changeSequence: function(SequenceName) {
		this.currentSequence($H(eval('this.SlideDefinition.'+SequenceName)));
		this.currentHowManys(0);
		this.handleSequenceBeginning();
		this.currentSecond(-1);
		//this.start();
	},

	/**
	* Avvia instantaneamente (al prossimo secondo) una sequenza specificata (slide interattiva)
	*/
	instantSequence: function(SequenceName) {
		// Se la slide e' in playing e non siamo gia' in InstantMode
		if (!this.InstantMode && this.isPlaying) {
			this.InstantMode = true;
			this.StopOnce = true;

			// Crea un nuovo layer Holder che verra' Fadeato e distrutto alla fine dell'InstantMode
			this.InstantHolder = this.pars.get('CreateInAbsoluteDiv') ? this.createInAbsoluteDiv() : this.createHolder();
			
			// Salva la posizione corrente dell'arrayLevel
			this.currentArrayLevel++;
			this.InstantModeLevel = this.currentArrayLevel;

			// Inietta la nuova sequenza al livello successivo
			this.currentSequence($H(eval('this.SlideDefinition.'+SequenceName)));
			this.currentHowManys(0);
			
			// Inizia la nuova sequenza iniettata
			this.handleSequenceBeginning();
			this.currentSecond(0);			
			
			this.nextSecond(true);
			
		}
	},	
	
	/**
	* Riporta dall'InstantMode al funzionamento normale
	*/
	restoreSequence: function() {
		// Solo se sei in instant mode
		if (this.InstantMode) {
			// Fada e distruggi il layer dell'InstantMode
			new Effect.Fade(this.InstantHolder, {onComplete:this.InstantHolder.remove});
			
			// Ripristina i valori dei livelli
			this.currentArrayLevel = this.InstantModeLevel-1;
			this.InstantHolder = null;
			this.InstantMode = false;
			
			// Se era stato stoppato riparti..
			if (!this.isPlaying)
				this.start();
		}
	},

	//--- UTILITY -------------------------------------------------------------------------------------------
	//-------------------------------------------------------------------------------------------------------

		findRealPosition: function(obj) {
			var curleft = curtop = 0;
			if (obj.offsetParent) {
				curleft = obj.offsetLeft
				curtop = obj.offsetTop
				while (obj = obj.offsetParent) {
					curleft += obj.offsetLeft
					curtop += obj.offsetTop
				}
			}
			return {'x': curleft, 'y': curtop};
		},
		
		RandomID: function() {
			var sRnd = '';
			var sChrs = 'abcdefghijklmnoqrstuwxyz';
			for (var i=0; i <= 16; i++) {
				var randomPoz = Math.floor(Math.random() * sChrs.length);
				sRnd += sChrs.substring(randomPoz,randomPoz+1);
			}
			return sRnd;
		}
	
}

//--------------------------------------------------
// Classe relativa alle IMMAGINI

	MOWImage = Class.create();
	MOWImage.prototype = {
		initialize: function(src) {
			this.isLoaded = false;
			this.setStyleOnLoad = false;
			this.src = src;
			this.width = 0;
			this.height = 0;
			this.lastStyle = {};

			// Crea un nuovo oggetto immagine (per il pre-caricamento)
			this.theObject = new Image();

			// Imposta un listener per l'avvenuto caricamento dell'immagine
			this.eventOnload  = this.onload.bindAsEventListener(this);
			this.theObject.onload = this.eventOnload;
			
			// Avvia il caricamento
			this.theObject.src = src;
		},
		
		/**
		* Imposta lo stile dell'immagine
		*/
		setStyle: function(style) {
			this.lastStyle = style;
			if (this.isLoaded)
				this.theObject.setStyle(style);
			else 
				this.setStyleOnLoad = true;
		},
		
		/**
		* Listener lanciato all'avvenuto caricamento dell'immagine
		*/
		onload:	function(event) {
			// Recupera informazioni sulla dimensione dell'immagine
			this.findImageSize();
			this.isLoaded = true;
			if (this.setStyleOnLoad)
				this.setStyle(this.lastStyle);
		},
		
		/**
		* Recupera informazioni sulla dimensione dell'immagine
		*/
		findImageSize: function() {
			
			// Ri-crea l'oggetto immagine (tanto l'immagine e' gia' caricata)
			this.theObject = new Element('img', {src: this.src});
		
			// Crea un layer "fuori-campo" e carica l'immagine in quel layer per saperne le dimensioni
			tmpLayer = new Element('div', {style:'position:absolute;top:-100px;left:-100px;width:5px;height:5px;overflow:hidden;'});
			document.body.appendChild(tmpLayer);
			tmpLayer.appendChild(this.theObject);
			
			// Salva informazioni sulla dimensione dell'immagine
			this.width = this.theObject.getWidth();
			this.height = this.theObject.getHeight();
			
			// Rimuove l'immagine e il layer fuori campo
			this.theObject.remove();
			tmpLayer.remove();
			
			// Se l'immagine e' una PNG e siamo in explorer 6 allora applica il filtro per gestire la trasparenza
			var imgName = this.src.toUpperCase();
      		if (imgName.substring(imgName.length-3, imgName.length) == "PNG" && this.isExplorer6()) {
				this.theObject = new Element('span', {style:'width:'+this.width+'px;height:'+this.height+'px;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=\'' + this.src + '\', sizingMethod=\'scale\');'});
			} else {
				this.theObject = new Element('img', {src: this.src});
			}

			// Imposta lo stile all'immagine
			this.setStyle(this.lastStyle);
			//alert('Immagine Caricata: '+this.src+' ['+this.width+'x'+this.height+']');
		},
		isExplorer6: function() {
			var IE6 = false /*@cc_on || @_jscript_version < 5.7 @*/;
			return IE6;		
		}
	};
	
//--------------------------------------------------
// Classe relativa al TESTO

	MOWText = Class.create();
	MOWText.prototype = {
		initialize: function() {
			this.isLoaded = true;
			this.width = 0;
			this.height = 0;

			this.theObject = new Element('div');
		},
		setStyle: function(style) {
			this.lastStyle = style;
			this.theObject.setStyle(style);
		}
	};
	
