/** 
 * Popups
 * Version 1.0.0
 */
var Popups = {
	windows: [], // Almacena los popups
	zIndexBase: 1000, // Nivel de capa desde donde se crean los popups
	container: null, // Capa en donde se crean los popups
	containerInitialHeight: null,
	multiple: true,
	cascada:true,
	acceptKeyEsc: true,
  /**
	 * Método que registra nuevos popups
	 */
	register: function(popup) {
    if(this.windows.length == 0) {
      if (this.acceptKeyEsc) {
				this.eventRemoveActive  = this.removeActive.bindAsEventListener(this);
				Event.observe(document, "keypress", this.eventRemoveActive);
			}
		}
		this.windows.push(popup);
		this.correctContainerHeight();
	},
  /**
	 * Método que suprime un popup
	 */
  unregister: function(popup) {
		this.windows = this.windows.reject(function(w) { return w==popup });
		this.correctContainerHeight()
    if(this.windows.length == 0) {
      if (this.acceptKeyEsc) {
      	Event.stopObserving(document, "keypress", this.eventRemoveActive);
			}
    }
	},
	
	removeActive: function (e) {
		if (this.getKeyCode(e) == Event.KEY_ESC) {
			this.getActive().destroy();
		}
	},
	getActive: function () {
		var index = 0;
		var maxIndex = 0;
		var active = null;
		var i = 0;
		for(i=0;i<this.windows.length;i++) {
			index = $(this.windows[i].id).getStyle('zIndex');
			if (maxIndex < index) {
				maxIndex = index;
				active = this.windows[i];
			}
		}
		
		return active;
	},
  /**
	 * Método que establece la capa en donde se van a crear los popups
	 */
	setContainer: function (container_id) {
		if ($(container_id)) {
			this.container = $(container_id);
		} else {
			this.container = $$('body')[0];
		}
		this.containerInitialHeight = this.container.getHeight();
	},
	
	setMultiple: function (value) {
		this.multiple = value;
	},
	
	setAcceptKeyEsc: function (value) {
		this.acceptKeyEsc = value;
	},
	correctContainerHeight: function () {
		var maxHeight = 0; // Contendrá la altura final elegida para el contenedor
		var marginTop; // Margen superior de la ventana emergente con respecto al contenedor
		var marginBottom; // Margen inferior de la ventana emergente con respecto al contenedor
		var height; // Altura de la ventana emergente
		// Se busca la ventana emergente cuya suma de su altura más sus margenes sea la mayor posible
		for (i=0; i<Popups.windows.length; i++) {
			marginTop = Popups.windows[i].getTop();
			height = Popups.windows[i].getHeight();
			marginBottom = Popups.windows[i].getBottom() + Popups.windows[i].options.restrictBottom;
			
			if (maxHeight<marginTop + height + marginBottom) {
				maxHeight = marginTop + height + marginBottom;
			}
		}
		
		// Se establece la altura del contenedor de ventanas emergentes
		if (maxHeight > Popups.containerInitialHeight) {
			Popups.container.setStyle({height: maxHeight + 'px'});
		} else {
			Popups.container.setStyle({height: Popups.containerInitialHeight + 'px'});
		}
	},
	
	getKeyCode: function (e) {
		if(!e) {
				//if the browser did not pass the event information to the
        //function, we will have to obtain it from the event register
        if( window.event ) {
            //DOM
            e = window.event;
        } else {
            //TOTAL FAILURE, WE HAVE NO WAY OF REFERENCING THE EVENT
            return undefined;
        }
    }
		if( typeof( e.keyCode ) == 'number' && e.keyCode != 0) {
        //IE, NS 6+, Mozilla 0.9+
        e = e.keyCode;
    } else if( typeof( e.which ) == 'number' && e.which != 0) {
        //NS 4, NS 6+, Mozilla 0.9+, Opera
        e = e.which;
    } else {
        //TOTAL FAILURE, WE HAVE NO WAY OF OBTAINING THE KEY CODE
        return undefined;
    }
		return e;
	}
};
/**
 * Clase que crea un popup
 */
var Popup = Class.create({
/**
 * Inicializa la clase
 */
	initialize: function() {
    
		var id; // Id del popup
		var optionIndex = 0; // Determina en donde se encuentra el objeto de opciones
		
    // Si existen argumentos
		if (arguments.length > 0) {
      if (typeof arguments[0] == "string" ) {
        id = arguments[0];
        optionIndex = 1;
      } else {
        id = arguments[0] ? arguments[0].id : null;
			}
		}
		// Si no se ha definido un id se crea uno de forma aleatoria
		if (!id) {
      id = "window_" + new Date().getTime();
		}
		// Si el id del popup ya existe se pone en el nivel más alto
		var popup;
		if (popup = Popups.windows.find(function(w) {return w.id==id})) {
			popup.bringToForward();
			return true;
		}

		this.id = id;
		
		if (Popups.container == null) {
			Popups.setContainer();
		}
		
		if (!Popups.multiple) {
			if (!Object.isUndefined(Popups.windows[0])) {
				Popups.windows[0].destroy();
			}
		}

		var defaults = {
			width: 200,
			height: 'auto',
			left: 0,
			top: 0,
			bottom: 0,
			position: null,
			restrictTop:0,
			restrictBottom:0,
			content:null
		}

		var options = Object.extend(defaults, arguments[optionIndex] || { });
		
		Object.extend(options, {
			popup: '<div id="'+this.id+'" class="popup"><div id="container_'+this.id+'" class="popup_container"><div id="handle_'+this.id+'" class="popup_handle"><div id="btn_close_'+this.id+'" class="popup_btn_close"></div></div><div id="content_'+this.id+'" class="popup_content"></div><div id="footer_'+this.id+'" class="popup_footer"></div></div></div>'
		});

		Popups.container.insert(options.popup);
		$(this.id).setStyle({width: options.width+'px'});
		$('content_'+this.id).insert(options.content);
		
		options.height = $(this.id).getHeight();
		
		if (options.position) {
			var position = options.position.split('-');
			var positionV = position[0];
			var positionH = position[1];
			var top = options.top;
			var left = options.left;
			var active = null;
			
			switch (positionV) {
				case 'top':
					top = top + options.restrictTop
				break;
				case 'center':
					var h = Popups.container.getHeight() - options.restrictTop - options.top - options.restrictBottom - options.bottom;
					top = parseInt((h - options.height)/2) + options.restrictTop + options.top;
				break;
				case 'bottom':
					top = parseInt(Popups.container.getHeight() - options.height - options.bottom-options.restrictBottom);
				break;
				case 'topvp':
					var scrollOffsetTop = document.viewport.getScrollOffsets().top;
					
					// Correccion cuando el popup es más grande que el visor del navegador
					if ((this.getHeight() < document.viewport.getHeight()) && (scrollOffsetTop > Popups.container.getHeight() - document.viewport.getHeight())) {
						scrollOffsetTop = Popups.container.getHeight() - document.viewport.getHeight();
					}
					
					// Cuando se ha restringido el margen superior (Normalmente cuando se usa una cabecera)
					if (options.restrictTop > scrollOffsetTop) {
						top = top + (options.restrictTop - scrollOffsetTop);
					}

					top = top + scrollOffsetTop;
					
				break;
				case 'centervp':
					var scrollOffsetTop = document.viewport.getScrollOffsets().top;
					
					// Correccion cuando el popup es más grande que el visor del navegador
					if ((this.getHeight() < document.viewport.getHeight()) && (scrollOffsetTop > Popups.container.getHeight() - document.viewport.getHeight())) {
						scrollOffsetTop = Popups.container.getHeight() - document.viewport.getHeight();
					}
					
					var h = document.viewport.getHeight();
					var offset = 0;

					if (options.restrictTop > scrollOffsetTop) {
						h = h - (options.restrictTop - scrollOffsetTop);
						offset = (options.restrictTop - scrollOffsetTop)
					}
					
					// Corrección cuando se ha deslizado el visor hasta el máximo posible (Normalmente cuando se usa pie de página)
					if (scrollOffsetTop + document.viewport.getHeight() > Popups.container.getHeight() - options.restrictBottom - options.bottom) {
						h = h-options.restrictBottom - options.bottom;
					}

					top = top + parseInt((h - options.height)/2) + scrollOffsetTop + offset;
					if (top - scrollOffsetTop < options.top) {
						top = top + options.top - (top - scrollOffsetTop);
					}
				
				break;
				case 'bottomvp':
					var h = document.viewport.getHeight();
					var scrollOffsetTop = document.viewport.getScrollOffsets().top;
					// Corrección cuando se ha deslizado el visor hasta el máximo posible (Normalmente cuando se usa pie de página)
					if (scrollOffsetTop + document.viewport.getHeight() > Popups.container.getHeight() - options.restrictBottom - options.bottom) {
						offset = scrollOffsetTop + document.viewport.getHeight() -(Popups.container.getHeight() - options.restrictBottom - options.bottom);
						h = h-offset - options.bottom;
					}

					top = parseInt(h - options.height) + document.viewport.getScrollOffsets().top;
				break;
				default:
					top = top + options.restrictTop
				break;
			}
			if (top < options.restrictTop + options.top) {
				top = options.restrictTop + options.top;
			}
			
			if (Popups.multiple && Popups.cascada && Popups.windows.length>0) {
				active = Popups.getActive();
				top = parseInt($(active.id).getStyle('top')) + 20;
			}
			$(this.id).setStyle({top:top+'px'});

			switch (positionH) {
				case 'center':
					left = parseInt((Popups.container.getWidth() - options.width)/2);
				break;
				case 'left':
					left = 0;
				break;
				case 'right':
					left = parseInt(Popups.container.getWidth() - options.width);
				break;
				default:
					left = 0;
				break;
			}
			if (left < 0) {
				left = 0;
			}
			if (Popups.multiple && Popups.cascada && Popups.windows.length>0) {
				active = Popups.getActive();
				left = parseInt($(active.id).getStyle('left')) + 20;
			}
			$(this.id).setStyle({left:left+'px'});
		}
		
		this.options = options;
		
		Popups.register(this);

		$(this.id).setStyle({zIndex:Popups.zIndexBase + Popups.windows.length});
		
    this.eventBringToForward = this.bringToForward.bindAsEventListener(this);
    Event.observe($('handle_'+this.id), "mousedown", this.eventBringToForward);
    Event.observe($(this.id), "mousedown", this.eventBringToForward);

    this.eventDestroy = this.destroy.bindAsEventListener(this);
		Event.observe($('btn_close_'+this.id), "click", this.eventDestroy);
		
		var _this = this;
		new Draggable(this.id,{
			handle:'handle_' + _this.id,
			endeffect: function (element) {return false},
			revert:function(element){return false},
			onStart:function(){
				_this.bringToForward();
			},
			onDrag:function(){return false},
			onEnd:function(){
				if (_this.getTop() < _this.options.restrictTop) {
					_this.setTop(_this.options.restrictTop + _this.options.top);
				}
				Popups.correctContainerHeight();
			}
		});
		
		return true;

	},
	
	bringToForward: function () {
		var i=0;
		var zIndex = $(this.id).getStyle('zIndex');
		for(i=0; i<Popups.windows.length;i++) {
			if ($(Popups.windows[i].id).getStyle('zIndex') > zIndex) {
				$(Popups.windows[i].id).setStyle({zIndex:$(Popups.windows[i].id).getStyle('zIndex')-1})
			}
		}
		$(this.id).setStyle({zIndex:Popups.zIndexBase + Popups.windows.length});
	},
	
	destroy: function () {
		Event.stopObserving($('handle_'+this.id), 'mousedown', this.eventBringToForward);
    Event.stopObserving($(this.id), 'mousedown', this.eventBringToForward);
    Event.stopObserving($('btn_close_'+this.id), 'click', this.eventDestroy);
		$(this.id).remove();
		Popups.unregister(this);
	},
	getHeight: function () {
		return $(this.id).getHeight();
	},
	getBottom: function () {
		return this.options.bottom;
	},
	getTop: function () {
		return parseInt($(this.id).getStyle('top'));
	},
	setTop: function (value) {
		$(this.id).setStyle({top:value+'px'});
	} 
});