
function Galeria (selector, oinit) {
	var self = {
			_anterior:       null,
			_contenedor:     null,
			_dim:            { docAncho: 0, docAlto: 0, winAncho: 0, winAlto: 0, scrollTop: 0, scrollLeft: 0},
			_fotoAnt:        null,
			_fotos:          null,	// array de objetos img
			_index:          0,
			_interval:       0,
			_numFotos:       0,
			_siguiente:      null,
			_slider:         null,
			_sliderLeft:     0,
			_sliderRight:    0,
			_sliderWidth:    0,
			_velo:           null,
			_veloContenedor: null,


			ampliar: function (event)	{
					this.velo ();
					this.init.x = event.pageX;
					this.init.y = event.pageY;
					this.presentacion (this._veloContenedor, event.data.index);
					return this;				
				},

			anterior: function () {
					if (this.init.circular || ! this.primero ()) this._next (false, true);
				},

			centrar: function (contenido) {
					var ancho = contenido.outerWidth (true);
					var alto  = contenido.outerHeight (true);
					var top   = (this._dim.winAlto - alto) / 2 + this._dim.scrollTop;
					var left  = (this._dim.winAncho - ancho) / 2 + this._dim.scrollLeft;

					contenido.css ({width: 0, height: 0, top: this.init.y, left: this.init.x, 'visibility': 'visible'});
					contenido.animate ({ width: ancho, height: alto, 'top': top, 'left': left}, 'slow', 
					                   function () 
					                   { 
					                   	$ ('img', self._veloContenedor).css ({left: $ (this).css ('left'), top: $ (this).css ('top')}); 
															// Creamos siguientey anterior y lo posicionamos
															self.controles (self._veloContenedor);
															if (self.init.controles) self.controlesPosicion ($ (self._fotos [self._index]));
					                   });
				},

			clearInterval: function () {
					if (this._interval)
					{	clearInterval (this._interval);
						this._interval = 0;
					}
				},

			close: function () {
						this.clearInterval ();
						if (this._velo) 
						{	$(document).unbind ('keydown.velo');
							this._velo.unbind ('click.velo');
							$(window).unbind ('resize.velo');  
							this._veloContenedor.fadeOut ('fast', function() { self._veloContenedor.remove (); self._veloContenedor = null; });				
							this._velo.fadeOut ('fast', function() { self._velo.remove (); self._velo = null; });				
						}
						return this; 
				},

			controles: function (contenedor) {
					if (this.init.controles)
					{	for (var i = this._fotos.length - 1; i >= 0; i--)
						{	this._fotos [i].click (function (event) { self.mouseEvents (event, 1) });
							this._fotos [i].mousemove (function (event) { self.mouseEvents (event, 2)});
							this._fotos [i].mouseover (function (event) { self.mouseEvents (event, 3)});
							this._fotos [i].mouseout (function (event) { self.mouseEvents (event, 4)});
						}
						
						this._siguiente = $ ('<img/>', { src: '/lib/jquery/imagenes/siguiente1.png'}).css ({position: 'absolute', left: 0, top: 0, opacity: 0, zIndex: 20});
						this._anterior  = $ ('<img/>', { src: '/lib/jquery/imagenes/anterior1.png'}).css ({position: 'absolute', left: 0, top: 0, opacity: 0, zIndex: 20});
						this._siguiente.mouseover (function () { self._siguiente.css ({opacity: 1});});
						this._siguiente.click (function () { self._next (true, true);});
						this._anterior.mouseover (function () { self._anterior.css ({opacity: 1});});
						this._anterior.click (function () { self._next (false, true);});
						contenedor.append (this._siguiente);
						contenedor.append (this._anterior);
					}
				},

			controlesPosicion: function (img) {
					var offsetImg = img.offset ();
					var altoImg   = img.height ();
					var anchoImg  = img.width ();
					var anchoAnt  = this._anterior.width ();
					var anchoSig  = this._siguiente.width ();
					
					// Coordenadas donde activamos siguiente anterior
					this._anterior._x1  = offsetImg.left; 
					this._anterior._x2  = this._anterior._x1 + anchoAnt + 35;
					this._siguiente._x2 = this._anterior._x1 + anchoImg;
					this._siguiente._x1 = this._siguiente._x2 - anchoSig - 35;

					// Si no hay mosaico la posicion es absoluta sobre relativa
					if (! this.init.mosaico) offsetImg = { left: 0, top: 0};

					// Posicionamos siguiente anterior
					this._siguiente.css ({left: offsetImg.left + anchoImg - anchoSig - 15, top: offsetImg.top + (altoImg - this._siguiente.height ()) / 2, opacity: 0});
					this._anterior.css ({left: offsetImg.left + 15, top: offsetImg.top + (altoImg - this._anterior.height ()) / 2, opacity: 0});
				},

			_dimensiones: function () {
					var doc = $ (document);
					var win = $ (window);

					if ($.browser.msie) 
					{	var dHeight = doc.height();
						var wHeight = win.height();
						this._dim = { docAncho:    window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, 
							            docAlto:     dHeight - wHeight < 20 ? wHeight : dHeight,
						            	winAncho: win.width (),
						            	winAlto: win.height (),
						            	scrollLeft: win.scrollLeft (), 
						            	scrollTop: win.scrollTop ()}; 
					} else
					{	this._dim = { docAncho: doc.width (),
							            docAlto: doc.height(), 
						  	          winAncho: win.width (),
						    	        winAlto: win.height (),
						      	      scrollLeft: win.scrollLeft (), 
						        	    scrollTop: win.scrollTop ()}; 
					}
			},

			finTransiccion: function () {
					this._fotos [this._index].css ('opacity', 1);
					for (var i = this._fotos.length - 1; i >= 0; i--) this._fotos [i].css ('opacity', i == this._index ? 1 : 0);
				},

			_fotoPresentacion: function (index) {

					if (this._fotoAnt) this._fotoAnt.css ({zIndex: 8});
					this._fotos [this._index].css ({zIndex: 9});
					this._fotoAnt = this._fotos [this._index];
					this._index = index;
					if (this._index >= this._numFotos) this._index = 0;
					if (this._index < 0) this._index = this._numFotos - 1;
					this._fotos [this._index].css ({zIndex: 10, opacity: 0}).animate ({opacity: 1}, this.init.transicion, function () { self.finTransiccion (); });
					this.siguienteAnterior ();
				},

			goto: function (index) { this._fotoPresentacion (index); },
				
			init: {
						alpha:             0.8,
						cerrarOnClick:     true,
						cerrarOnEscape:    true,
						circular:          true,
						click:             null,
						color:             '#fff',
						controles:         false,
						css:               {},
						fotos:			       Array (),
						mosaico:           false,
						play:              true,
						slider:            false,
						timer:             4000,
						transicion:        1000,
						x:                 0,
						y:                 0,
						zIndex:            1000,
						zoom:              false
				},
			
			load:	function (oinit) {
						if (typeof oinit == 'undefined') oinit = {};
						if (oinit.slider || oinit.mosaico) this.init.circular = false; // Si es un slider o un mosaico desactiva la propiedad circular
						this.init.height = this._contenedor.outerHeight (true);
						this.init.width  = this._contenedor.outerWidth (true);
						$.extend (true, this.init, oinit);
						if (this.init.mosaico) this.mosaico ();
						else if (this.init.slider) this.slider ();
						else
						{ this._contenedor.css ({position: 'relative', height: this.init.height, width: this.init.width});
							this.presentacion (this._contenedor, 0);
						}
						// Inicializa los controles de siguiente y anterior
						if (this.init.siguiente) this.init.siguiente.element.click ({self: this}, function (e) { e.data.self.siguiente (); });							
						if (this.init.anterior) this.init.anterior.element.click ({self: this}, function (e) { e.data.self.anterior (); });							
						if (this.init.siguiente && this.init.anterior) this.siguienteAnterior ();
					},
					
			mosaico: function () {
						for (var i = 0; i < this.init.fotos.length; i++)
						{	var img = $ ('<img/>', { src: this.init.fotos [i].mini, index: i}).css ('cursor', 'pointer');
							if (this.init.click) img.click ({galeria: self, index: i}, function (event) { event.data.galeria.init.click (event.data.galeria, event.data.index) });
							else img.click ({galeria: self, index: i}, function (event) { event.data.galeria.ampliar (event) }) ;
							this._contenedor.append (img);
						}
					},

			mouseEvents: function (event, tipo) {
					if (tipo == 1) // click
					{	if (event.pageX >= this._anterior._x1 && event.pageX <= this._anterior._x2) this._next (false, true);
						else if (event.pageX >= this._siguiente._x1 && event.pageX <= this._siguiente._x2) this._next (true, true);
					} else if (tipo == 2) //move
					{	this._anterior.css ({opacity: event.pageX >= this._anterior._x1 && event.pageX <= this._anterior._x2 ? 1 : 0});
						this._siguiente.css ({opacity: event.pageX >= this._siguiente._x1 && event.pageX <= this._siguiente._x2 ? 1 : 0});
					} else if (tipo == 3)	// over
						this.controlesPosicion ($ (event.target));
					else if (tipo == 4)	// out
					{	this._siguiente.css ({opacity: 0});
						this._anterior.css ({opacity: 0});
					}

				},
					
			_next: function (siguiente, stop) {
					if (stop) this.clearInterval ();
					if (this.init.slider) {
						if (siguiente) this._sliderLeft -= this._sliderWidth;
						else this._sliderLeft += this._sliderWidth;
						this._slider.animate ({left: this._sliderLeft}, 'slow', 'swing');
						this.siguienteAnterior ();
					} else {	// Presentacion
						if (siguiente && this._fotos [this._index < this._numFotos -1 ? this._index + 1 : 0].data ('loaded')) this._fotoPresentacion (this._index + 1);
						else if (! siguiente && this._fotos [this._index > 0 ? this._index -1 : this._numFotos - 1].data ('loaded')) this._fotoPresentacion (this._index - 1);
					}
				},

			presentacion: function (contenedor, index) {
						var l = this.init.fotos.length;

						this._index = index;
						// Creamos los componentes de imagenes
						this._fotos = Array ();
						for (var i = 0; i < l; i++)
						{	var css = {position: 'absolute', left: 0, top: 0, opacity: i == index ? 1 : 0, zIndex: i == index ? 10 : 8};
							$.extend (css, this.init.css);
							var img = $ ('<img/>').css (css);
							if (this.init.mosaico && i == index) img.css ('visibility', 'hidden');
							img.load ({centrar: i == index}, function (event) 
							                      { 
							                      	$ (this).data ('loaded', true); 
							                      	if (event.data.centrar && self.init.mosaico) self.centrar ($ (this));
							                      });
							// Si lleva enlace no funciona siguiente anterior ?????
							if (this.init.fotos [i].enlace)
								contenedor.append ($ ('<a/>', { href: this.init.fotos [i].enlace, target: this.init.fotos [i].blank ? '_blank' : ''}).append (img));
							else {
								if (this.init.zoom) img.css ({cursor: 'pointer'}).click (function (e) { self._zoom (this) });
								contenedor.append (img);
							}
							this._fotos.push (img);
						}
						// Cargamos las imagenes despues de que se hayan creado los componentes
						if (! this.init.mosaico) this.controles (contenedor);
						this._fotos [index].attr ('src', this.init.fotos [index].foto);
						for (var i = 0; i < l; i++)	if (i != index) this._fotos [i].attr ('src', this.init.fotos [i].foto);
						this._numFotos = this._fotos.length;
						if (this._numFotos > 1 && this.init.play) this._interval = setInterval (function () { self._next (true, false)}, this.init.timer);
				},

			primero: function () { 

					if (this.init.slider) return this._sliderLeft >= 0;
					return this._index == 0 && this._numFotos 
				},

			_resize: function () {
					if (this._velo) 
					{	this._dimensiones ();				
						this._velo.css ( {width: this._dim.docAncho, height: this._dim.docAlto});
						if (this.init.zoom && this.init.zoom.img) this._centrarZoom ();
						// QUIZAS CENTRAR EL CONTENEDOR	cuidado con duplicar los eventos
					}				
				},
				
			siguiente: function () {
					if (this.init.circular || ! this.ultimo ()) this._next (true, true);
				},

			siguienteAnterior: function () {
					if (! this.init.circular) {
						if (this.init.siguiente && this.init.siguiente.element && this.init.siguiente.on && this.init.siguiente.off) {
							if (this.ultimo ()) this.init.siguiente.element.attr (this.init.siguiente.off).css ({cursor: 'default'});
							else this.init.siguiente.element.attr (this.init.siguiente.on).css ({cursor: 'pointer'});
						}
						if (this.init.anterior && this.init.anterior.element && this.init.anterior.on && this.init.anterior.off) {
							if (this.primero ()) this.init.anterior.element.attr (this.init.anterior.off).css ({cursor: 'default'});
							else this.init.anterior.element.attr (this.init.anterior.on).css ({cursor: 'pointer'});
						}
					}
				},

			slider: function () {

					var ancho = 0;
					this._slider  = $ ('<div/>').css ({ position: 'relative', left: 0});
					this._contenedor.css ({ overflow: 'hidden', position: 'relative'});
					this._contenedor.append (this._slider);

					for (var i = 0; i < this.init.fotos.length; i++) {
						var div = $ ('<div/>').css ({float: 'left'});
						var img = $ ('<img/>', { src: this.init.fotos [i].foto, index: i}).css ('cursor', 'pointer');
						if (this.init.click) img.click ({galeria: self, index: i}, function (event) { event.data.galeria.init.click (event.data.galeria, event.data.index) });

						div.append (img);
						this._slider.append (div);
						ancho += div.outerWidth (true);
					}
					this._slider.css ({width: ancho});
				 	this._sliderLeft  = 0;
				 	this._sliderRight = this._slider.outerWidth (true);
				 	this._sliderWidth = this._contenedor.innerWidth (true);
				},
			
			ultimo: function () { 
					if (this.init.slider) return this._sliderLeft - this._sliderWidth <= -this._sliderRight;
					return this._index == this._numFotos - 1 && this._numFotos 
				},

			_centrarZoom: function () {

					var width = this.init.zoom.width;
					var height = this.init.zoom.height;

					if (width > this._dim.winAncho || height > this._dim.winAlto) {
						if (height < this._dim.winAlto) {
							width = this._dim.winAncho;
							height = width * this.init.zoom.height / this.init.zoom.width;
						} else if (width < this._dim.winAncho) {
							height = this._dim.winAlto;
							width  =  height * this.init.zoom.width / this.init.zoom.height;
						} else  {
							if (width / this._dim.winAncho > height / this._dim.winAlto) {
								width = this._dim.winAncho;
								height = width * this.init.zoom.height / this.init.zoom.width;
							} else {
								height = this._dim.winAlto;
								width  =  height * this.init.zoom.width / this.init.zoom.height;
							}
						}
					}

					var left = (this._dim.winAncho - width) / 2;
					var top  = (this._dim.winAlto - height) / 2;
					this.init.zoom.img.css ({left: left, top: top, width: width, height: height});
				},
				
			_zoom: function (img) {
					
					this.velo ();
					this.init.zoom.img = $ ('<img/>', {src: img.src}).css ({position: 'absolute'}).click (function () {self.close ();});
					this._centrarZoom ();
					this._veloContenedor.append (this.init.zoom.img);
					console.log ('a');
					return this;
				},
			
			velo: function () {
					this._velo = $ ('<div/>');
					$ ('body').append (this._velo);
					this._dimensiones ();
					this._velo.css ({ position: 'absolute',
								            top: 0,
								            left: 0,
								            width: this._dim.docAncho,
								            height: this._dim.docAlto,
								            display: 'none',
								            opacity: 0,
								            backgroundColor: this.init.color,
								            zIndex: this.init.zIndex});
					if (this.init.cerrarOnEscape) $(document).bind('keydown.velo', function (event) { if (event.keyCode == 27) self.close (event); });
					if (this.init.cerrarOnClick)this._velo.bind ('click.velo', function (event) { self.close (event); });					
					$(window).bind('resize.velo', function () { self._resize(); });
					this._velo.css ({display: 'block'}).fadeTo ('slow', this.init.alpha, function() { self._resize (); });
					this._veloContenedor = $ ('<div/>');
					this._veloContenedor.css ({ width: 0, height: 0, position: 'absolute', left: 0, top: 0, zIndex: this.init.zIndex + 1});
					$ ('body').append (this._veloContenedor);
				}
				
	}	// end self

	self._contenedor = $ (selector);
	if (self._contenedor.length) {
		self._contenedor.empty ();
		self.load (oinit);
	}
	return self;
}


