/**
 * Dependencias
 * 		Prototype 1.6.1 (no testeado en versiones anteriores).
 * 		Script.aculo.us		Effect
 * 
 * Instrucciones de uso:
 * 		- Los enlaces con la clase "ProtoWinLink" se prepararán automaticamnete para abrirse en un ProtoWin
 * 		- Se crean nuevas ventanas instanciando la clase ProtoWin.
 * 		- Al crear un ProtoWin, carga el contenido según el siguiente proceso:
 * 			- Si está activa la opción isImage, carga la imagen en el ProtoWin.
 * 			- Si está activa la opción isUrl, carga la url dentro del ProtoWin.
 * 			- Si detecta estructura de imagen y la opción isImage no es false, carga la imagen en el ProtoWin.
 * 			- Si detecta estructura de URL y la opción isUrl no es false, carga la URL en el ProtoWin.
 * 			- Carga el contenido en el ProtoWin como texto plano. 
 *  
 * BUGS
 *		- [FIXED]>=IE6 -> Los campos input se ven por encima de la ventana y del fondo.
 *		- WEBKIT -> Problema con con el posicionamiento de las capas interiores.
 */


/*
 * Extendemos Prototype.BrowserFeatures para que indique la versión de Intermet Explorer.
 */
if(Prototype.Browser.IE){
	if(parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6) Prototype.BrowserFeatures['IEVersion']=6;
	else if(parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5))) Prototype.BrowserFeatures['IEVersion']=7;
	else Prototype.BrowserFeatures['IEVersion']=8;
}


/*
 * Buscamos los enlaces con clase ProtoWinLink para hacer que carguen en un ProtoWin. 
 */
document.observe('dom:loaded',function(){
	$$('a.protoWinLink').each(function(a){
		a.observe('click',function(e){
			e.stop();
			new ProtoWin(e.currentTarget.href,{isUrl:true});
		});
	});
	$$('a.protoWinImg').each(function(a){
		a.observe('click',function(e){
			e.stop();
			new ProtoWin(e.currentTarget.href,{isImg:true});
		});
	});
});

var ProtoWin = Class.create({
	
	options_layout: {
		id: null,				// Id que se le pondrá al objeto ventana
		innerId:null,			// Id de la capa contenedora.
		isUrl: null,			// Indica si el contenido es una url(true: Fuerza a que lo trate como una URL, false: Fuerza a que no se cargue como una URL, null: Si detecta estructura de URL lo carga como tal.)
		isImage: null,			// Indica si es una imagen (true: Fuerza a que lo trate como una imagen, false: Fuerza a que no se cargue como una imagen, null: Si detecta estructura de imagen lo carga como tal.)
		autoCenter: false,		// Autocentra la pantalla cuando se recarga el contenido. NO IMPLEMENTADO
		autoScale: true,		// Dimensiona la ventana automaticamente cuando se recarga el contenido. NO IMPLEMENTADO
		backBlock: true,		// Indica si se bloquea el fondo de la pantalla
		position: {				// Posición en la que se crea la ventana. NO IMPLEMENTADO
			x: null,
			y: null
		},
		classes: {
			auto: 'ProtoWin-link',				// Clase que se le aplica a los enlaces, que abren una ventana
			window: 'ProtoWin',					// Objeto que contiene la ventana
			container: 'container',				// 
			header: 'header',					// Cabecera de la ventana (NO ESTÁ EN USO)
			bottomBar: 'bottomBar',				// Barra inferior (NO ESTÁ EN USO)
			closeButton: 'closeButton',			// Botón de cerrar
			outerContainer: 'outer-container',	// 
			backScreen: 'backScreen'			// Pantalla de oscurecer
		},
		texts: {
			closeButton: '[Cerrar]', 			// Texto del botón de cerrar
			ajaxError: '<span class="alert">Error al conectar con el servidor</span>'
		},
		animations: {
			'resize':{duration:0.5},
			'appear': {to:1,duration:0.5}
		}
	},
	
	window: null,		// Elemento de la ventana principal
	container: null,	// Elemento contenedor de la ventana
	screen: null,		// Pantalla de bloqueo de fondo
	
	/**
	 * PUBLICA
	 * Recibe un contenido y lo muestra en una ventana emergente
	 * @param {mixed} content: El contenido a mostrar.
	 * @param {object} options: Objeto de opciones.
	 */
	
	initialize: function(content,options){
		// Cargamos las opciones.
		this.options = Object.clone(this.options_layout);
		if (options) {
			Object.extend(this.options.texts, options.texts); delete (options.texts);
			Object.extend(this.options.classes, options.classes); delete (options.classes);
		}
		Object.extend(this.options,options);
		// Si es una url, la cargamos en el contenedor
		if (this.options.isImage == true || this.options.isImage!== false && (/.*\.[jpg|jpeg|png|gif]$/.test(content))) { // Comprobamos que sea una imagen
			content = new Element('img',{src:content,alt:'ProtoWin'});
		}else if(this.options.isUrl == true || this.options.url == true || this.options.isUrl !== false && (/^https?:\/\//.test(content))) { // Comprobamos que sea un archivo
			
			new Ajax.Request(content, {
				onSuccess: function(r){this.reload(r.responseText);}.bind(this),
				onFailure: function(r){this.reload(this.options.texts.ajaxError);
			}.bind(this)});
			content = new Element('div').addClassName('loading');
		}
		this.drawWindow(content);
		return this;
	},
	
	/**
	 * PUBLICA
	 * Cambia el contenido de la ventana y la redimensiona para adaptarse.
	 * 
	 * @param {Object} content: Contenido a insertar en la ventana.
	 */
	reload: function(content){
		// Si no está creada la ventana, la crea
		if(!this.window) this.drawWindow(content);
		
		var actualSize = this.window.getDimensions(); // Guardamos el tamaño actual del elemento.
		this.container.update(content); // Rellenamos el container con el nuevo contenido.
		var newSize = this.window.getDimensions(); // Guardamos el tamaño del container con el nuevo contenido.
		this.window.setStyle({ // Volvemos a dar al container el tamaño del principio.
			width: actualSize.width+'px',
			height: actualSize.height+'px'
		});
		// Preparamos el objeto de las nuevas características del container
		var newStyle = {
			width: newSize.width + 'px',
			height: newSize.height + 'px',
			marginLeft: '-'+(newSize.width/2)+'px',
			marginTop: '-'+(newSize.height/2)+'px'
		};
		
		// Fix IE 6
		if(Prototype.Browser.IE && Prototype.BrowserFeatures.IEVersion<=6){
			newStyle.left = (document.viewport.getScrollOffsets()[0] + document.viewport.getWidth() / 2 - newSize.width / 2) + 'px';
			newStyle.top = (document.viewport.getScrollOffsets()[1] + document.viewport.getHeight() / 2 - newSize.height / 2) + 'px';
		}
		
		// Aplicamos la transformación desde el primer estado al estado actual
		this.container.hide(); // Escondemos
		this.window.animation = this.window.morph('error',Object.extend({
			style: newStyle,
			afterFinish: function(){
				this.container.setOpacity(0);
				this.container.show();
				new Effect.Opacity(this.container,{from:0,to:1,duration:0.5});
			}.bind(this)
		},this.options.animations.resize));
	},
	
	/**
	 * PUBLICA
	 * Cierra y destruye la ventana
	 */
	close: function(){
		new Effect.Opacity(this.window,{to: 0,duration: 0.3,afterFinish: function(){this.window.remove()}.bind(this)}); // Eliminamos la ventana	
		if($$('div.'+this.options.classes.backScreen).size()>0){new Effect.Opacity(this.screen,{to:0,duration:0.3,afterFinish:function(){this.screen.remove()}.bind(this)});} // Eliminamos el bloqueo de fondo
	},
	
	/**
	 * PRIVADA
	 * Dibuja el elemento de la ventana
	 * @param {Object} content
	 */
	drawWindow: function(content){
		if (this.options.backBlock) this.drawBkgr();
		
		this.window = new Element('div',{'id':this.options.id}) // Capa contenedora de la ventana completa
			.addClassName(this.options.classes.window)
			.insert(new Element('a').addClassName(this.options.classes.closeButton).observe('click',this.close.bind(this)).insert(this.options.texts.closeButton)) // Botón de cerrar
			.insert(this.outerContainer = new Element('div',{'id':this.options.innerId}).addClassName(this.options.classes.outerContainer)
				.insert(this.container = new Element('div').addClassName(this.options.classes.container)
					.insert(content)
				)	
			);
		
		$$('body')[0].insert(this.window); // La insertamos en pantalla
		
		this.window.setStyle({ // La preparamos
			position: 'absolute', top: '50%', left: '50%',
			marginLeft: '-' + (this.window.getDimensions().width / 2) + 'px',
			marginTop: '-' + (this.window.getDimensions().height / 2) + 'px',
			opacity:0
		});
		new Effect.Opacity(this.window,Object.extend({},this.options.animations.appear)); // La mostramos con efecto
		return;
	},
	
	/**
	 * PRIVADA
	 * Dibuja el fondo de la pantalla.
	 */
	drawBkgr: function (){
		// Creamos el fondo
		this.screen = new Element('div').addClassName(this.options.classes.backScreen).observe('click',this.close.bind(this));
		$$('body')[0].insert(this.screen); // Insertamos en el documento		
		this.screen.setStyle({ // Le damos las medidas
			position: 'fixed',
			right: 0, top:0, width:'100%', height:'100%',
			opacity: 0
		});
		
		new Effect.Opacity(this.screen, {to: 0.5,duration: 0.5});
	}
	
});
