var zindex = 50;
var minimizedDialogs = [];
var positionsAvailable = [];
var positionsTaken = [];
var checkingMinimized = false;

for (i = 0; i < 49; i++) {
	positionsAvailable.push(-1);
}

var Dialog = new Class({
	initialize: function(type) {
		this.dialogBackground = new Element("div");
		this.dialogBackground.addClass("dialog_background");
		
		this.dialog = new Element("div");
		this.dialog.addClass("dialog");
		this.dialog.addClass("dialog_content");
		
		this.dialogBackground.setStyle("position", 'fixed');
		//this.dialog.setStyle("position", 'fixed');
		
		this.dialogBackground.injectInside(document.body);
		this.dialog.injectInside(document.body);
		
		this.dialogType = type;
		this.dialogStatus = "invisible";
		this.lastAdded = false;
		this.lastEffect = now();
		this.effectDelay = 0;
		this.morphEffect = this.empty;
		this.moveEffect = this.empty;
		this.acceptControl = new Element('div');
		this.cancelControl = new Element('div');
		
		this.prevWidth = 0;
		this.prevHeight = 0;
		this.multiplier = 1;
		
		this.dialogBackground.setStyle("display", "none");
		this.dialog.setStyle("display", "none");
		
		//Controles
		dialogControls = new Element("table", {'cellpadding': 0, 'cellspacing': 0, 'border': 0}).injectInside(this.dialog);
		dialogControlsTbody = new Element("tbody").injectInside(dialogControls);
		dialogControlsTr = new Element("tr").injectInside(dialogControlsTbody);
		dialogControlsTr2 = new Element("tr").injectInside(dialogControlsTbody);
		
		//Titulo
		dialogControlsTdTitle = new Element("td").injectInside(dialogControlsTr);
		this.dialogTitle = new Element("div");
		
		if (this.dialogType & Dialog.TITLE) this.dialogTitle.injectInside(dialogControlsTdTitle);
		this.dialogTitle.addClass("dialog_title");
		this.setTitle("Di&aacute;logo");
		
		//this.dialog.makeDraggable();
		//this.dialog.makeDraggable({handle: this.dialogTitle});
		
		colSpan = 1
		//Minimizar
		if (this.dialogType & Dialog.MINIMIZE) {
			this.dialogTitle.addEvent('click', this.toggleTitle.bind(this));
			
			this.minimizeControl = new Element("td", {}).injectInside(dialogControlsTr);
			this.minimizeControl.setHTML("Min");
			this.minimizeControl.addEvent('click', this.toggle.bind(this));
			this.minimizeControl.setStyle('cursor', 'pointer');
			
			colSpan ++;
		}
		
		//Cerrar
		if (this.dialogType & Dialog.CLOSE) {
			dialogControlsTdClose = new Element("td", {'align': 'right' }).injectInside(dialogControlsTr);
			dialogControlsTdClose.setHTML("&nbsp;&nbsp;X&nbsp;&nbsp;");
			dialogControlsTdClose.addEvent('click', this.hide.bind(this));
			dialogControlsTdClose.setStyle('cursor', 'pointer');
			
			colSpan ++;
		}
		
		//Contenido
		this.dialogContent = new Element("td", {'colspan': colSpan}).injectInside(dialogControlsTr2);
		
		//Aceptar y cancelar
		if ((this.dialogType & Dialog.ACCEPT) && (this.dialogType & Dialog.CANCEL)) {
			//Juntos
			dialogControlsTrCont = new Element("tr").injectInside(dialogControlsTbody);
			dialogControlsTdCont = new Element("td", {'colspan': colSpan}).injectInside(dialogControlsTrCont);
			
			dialogControlsTableConfirm = new Element("table", {'width': '100%'}).injectInside(dialogControlsTdCont);
			dialogControlsTbodyConfirm = new Element("tbody").injectInside(dialogControlsTableConfirm);
			dialogControlsTrConfirm = new Element("tr").injectInside(dialogControlsTbodyConfirm);
			dialogControlsTdAccept = new Element("td", {'align': 'left'}).injectInside(dialogControlsTrConfirm);
			dialogControlsTdCancel = new Element("td", {'align': 'right'}).injectInside(dialogControlsTrConfirm);
			
			dialogControlsTdAccept.setHTML("[aceptar]");
			dialogControlsTdAccept.addEvent('click', this.hide.bind(this));
			dialogControlsTdAccept.setStyle('cursor', 'pointer');
			
			dialogControlsTdCancel.setHTML("[cancelar]");
			dialogControlsTdCancel.addEvent('click', this.hide.bind(this));
			dialogControlsTdCancel.setStyle('cursor', 'pointer');
			
			this.acceptControl = dialogControlsTdAccept;
			this.cancelControl = dialogControlsTdCancel;
		} else {
			//Separados
			//Aceptar
			if (this.dialogType & Dialog.ACCEPT) {
				dialogControlsTrAccept = new Element("tr").injectInside(dialogControlsTbody);
				dialogControlsTdAccept = new Element("td", {'colspan': colSpan}).injectInside(dialogControlsTrAccept);
				dialogControlsTdAccept.setHTML("[aceptar]");
				dialogControlsTdAccept.addEvent('click', this.hide.bind(this));
				dialogControlsTdAccept.setStyle('cursor', 'pointer');
				
				this.acceptControl = dialogControlsTdAccept;
			}
			
			//Cancelar
			if (this.dialogType & Dialog.CANCEL) {
				dialogControlsTrCancel = new Element("tr").injectInside(dialogControlsTbody);
				dialogControlsTdCancel = new Element("td", {'colspan': colSpan}).injectInside(dialogControlsTrCancel);
				dialogControlsTdCancel.setHTML("[cancelar]");
				dialogControlsTdCancel.addEvent('click', this.hide.bind(this));
				dialogControlsTdCancel.setStyle('cursor', 'pointer');
				
				this.cancelControl = dialogControlsTdCancel;
			}
		}
		
		//Si puede minimizarse
		if (this.dialogType & Dialog.MINIMIZE) {
			this.morphEffect = new Fx.Morph(this.dialog, {duration: 250 * this.multiplier});;
			this.moveEffect = new Fx.Morph(this.dialog, {duration: 1000 * this.multiplier, transition: Fx.Transitions.Expo.easeOut});
		}
	},
	setTitle: function(aTitle) {
		this.dialogTitle.setHTML(aTitle);
	},
	setEffectsMultiplier: function(aValue) {
		if (aValue < 0) aValue = 0;
		this.multiplier = aValue;
	},
	
	show: function(anElement) {
		if (this.dialogStatus == "visible") {
			//Si ya esta visible, lo mueve al medio
			var moveTo = new Fx.Morph(this.dialog, {duration: 1000, transition: Fx.Transitions.Elastic.easeOut});
			
			var coord = this.dialog.getCoordinates();
			moveTo.start({"left": '50%', "bottom": '50%', 
				"margin-left": (coord.width / 2) + "px",
				"margin-bottom": (coord.height / 2) + "px"});
			return false;
		}
		if (now() - this.lastEffect > this.effectDelay) {
			anElement = $(anElement);
			if (this.lastAdded) this.lastAdded.setStyle("display", "none");
			if (this.lastAdded) {
				this.lastAdded.setStyle("display", "none");
				if (this.lastAdded.realParent) this.lastAdded.realParent.appendChild(this.lastAdded)
			}
			
			this.dialogBackground.setStyle("z-index", zindex);
			zindex ++;
			
			this.dialog.setStyle("z-index", zindex);
			zindex ++;
			
			if (!anElement.realParent) anElement.realParent = anElement.parentNode;
			anElement.injectInside(this.dialogContent);
			this.lastAdded = anElement;
			
			this.dialogStatus = "visible";
			
			this.dialog.setStyle("opacity", 0);
			this.dialogBackground.setStyle("opacity", 0);
			
			anElement.setStyle("display", "");
			if (this.dialogType & Dialog.BACKGROUND) this.dialogBackground.setStyle("display", "");
			this.dialog.setStyle("display", "");
			
			var coord = this.dialog.getCoordinates();
			var size;
			if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
				size = new Object();
				size.width = document.body.clientWidth;
				size.height = document.body.clientHeight;
			} else {
				size = document.body.getCoordinates();
			}
			
			if (size.width > window.screen.availwidth) size.width = window.screen.availwidth;
			if (size.height > window.screen.availheight) size.height = window.screen.availheight;
			var pos = window.getScroll();
			pos.x = 0;
			
			var left = pos.x + (size.width / 2) - (coord.width / 2);
			var top = pos.y + (size.height / 2) - (coord.height / 2)
			if (left < 0) left = 0;
			if (top < 0) top = 0;
			this.dialog.setStyle("left", left);
			this.dialog.setStyle("top", top);
			
			this.dialog.get('tween', {property: "opacity", duration: 500 * this.multiplier}).start(1);
			this.dialogBackground.get('tween', {property: "opacity", 
				duration: 500 * this.multiplier}).start(0.4);
			
			this.lastEffect = now();
			this.effectDelay = 500 * this.multiplier;
		} else {
			var fx = function () {
				this.show(anElement);
			}.delay(this.effectDelay - (now() - this.lastEffect) + 100, this);
		}
	},
	hide: function() {
		if (this.dialogStatus == "invisible") return false;
		if (now() - this.lastEffect > this.effectDelay) {
			this.dialog.get('tween', {property: "opacity", duration: 250 * this.multiplier}).start(0);
			this.dialogBackground.get('tween', {property: "opacity", 
				duration: 250 * this.multiplier}).start(0);
			
			dialog = this;
			var fx = function () {
				if (this.lastAdded) {
					this.lastAdded.setStyle("display", "none");
					if (this.lastAdded.realParent) this.lastAdded.realParent.appendChild(this.lastAdded)
				}
				this.lastAdded = false;
				this.dialogStatus = "invisible";
			
				if (this.dialogType & Dialog.BACKGROUND) this.dialogBackground.setStyle("display", "none");
				this.dialog.setStyle("display", "none");
				removeMinimizedDialog(this);
			}.delay(300 * this.multiplier, this);
			
			this.lastEffect = now();
			this.effectDelay = 0 * this.multiplier;
		} else {
			var fx = function () {
				this.hide();
			}.delay(this.effectDelay - (now() - this.lastEffect) + 100, this);
		}
	},
	
	//Minimizar
	minimize: function() {
		if (this.dialogStatus == "visible" && (this.dialogType & Dialog.MINIMIZE)) {
			//Minimiza si se ve el dialogo y tiene la opcion para minimizar
			if (now() - this.lastEffect < this.effectDelay) return false;
			if (addMinimizedDialog(this)) {
				this.dialog.setStyle("z-index", 999999);
			
				this.minimizeControl.setHTML("");
				this.dialogStatus = "minimized";
				
				//Le sacamos el background
				this.dialogBackground.get('tween', {property: "opacity", 
					duration: 300 * this.multiplier}).start(0);		
				
				coord = this.dialog.getCoordinates();
				
				if (window.ie) {
					this.prevWidth = coord.width;
					this.prevHeight = coord.height;
				} else {
					this.prevWidth = coord.width - 15;
					this.prevHeight = coord.height - 15;
				}
			
				//Lo movemos
				/*this.moveEffect.start({
					'bottom': (parseInt(minimizedDialogs.length / 7) * 32),
					'left': ((minimizedDialogs.length % 7) * 135)
				});*/
				
				//Lo hacemos chiquito
				this.morphEffect.start("dialog_minimized");
				this.lastEffect = now();
				this.effectDelay = 1000 * this.multiplier;
				
				var fx = function() {
					this.dialogContent.setStyle("display", 'none')
					this.minimizeControl.setHTML("Max");
				}.delay(1000 * this.multiplier, this);
			}
			
			//Lo agregamos a la lista
		} else {
			this.hide();
		}
		return true;
	},
	//Maximizar
	maximize: function() {
		if (this.dialogStatus == "minimized" && (this.dialogType & Dialog.MINIMIZE)) {
			//Minimiza si se ve el dialogo y tiene la opcion para maximizar
			if (now() - this.lastEffect < this.effectDelay) return false;
			
			this.dialogContent.setStyle("display", '');
			this.dialogBackground.setStyle("z-index", zindex);
			zindex ++;
			this.dialog.setStyle("z-index", zindex);
			zindex ++;
		
			this.minimizeControl.setHTML("");
			this.dialogStatus = "visible";
			
			//Le sacamos el background
			this.dialogBackground.get('tween', {property: "opacity", 
				duration: 300 * this.multiplier}).start(0.4);		
			
			//Lo hacemos grande
			this.morphEffect.start("dialog_content");
			
			
			//Lo movemos
			fx = function() {
				coord = this.dialog.getCoordinates();
				this.moveEffect.start({
					'bottom': '50%',
					'left': '50%',
					"margin-left": (coord.width / 2) + "px",
					"margin-bottom": (coord.height / 2) + "px",
					'width': this.prevWidth,
					'height': this.prevHeight
				});
				
				this.lastEffect = now();
				this.effectDelay = 1100 * this.multiplier;
				
				var fx = function() {
					this.minimizeControl.setHTML("Min");
				}.delay(1000 * this.multiplier, this);
				
				//Lo sacamos de la lista
				removeMinimizedDialog(this);
			}.delay(100 * this.multiplier, this)
		} else {
			this.hide();
		}
		return true;
	},
	//Maximiza o Minimiza
	toggle: function() {
		toRet = true;
		if (this.dialogStatus == "visible" && (this.dialogType & Dialog.MINIMIZE)) {
			toRet = this.minimize();
		} else {
			if (this.dialogStatus == "minimized" && (this.dialogType & Dialog.MINIMIZE)) {
				toRet = this.maximize();
			}
		}
		
		if (!toRet) {
			var fx = function() {
				this.toggle();
			}.delay(this.effectDelay - (now() - this.lastEffect) + 10, this);
		}
		return toRet;
	},
	toggleTitle: function() {
		toRet = true;
		if (this.dialogStatus == "visible" && (this.dialogType & Dialog.MINIMIZE)) {
			return false;
		} else {
			if (this.dialogStatus == "minimized" && (this.dialogType & Dialog.MINIMIZE)) {
				toRet = this.maximize();
			}
		}
		
		if (!toRet) {
			var fx = function() {
				this.toggleTitle();
			}.delay(this.effectDelay - (now() - this.lastEffect) + 10, this);
		}
		return toRet;
	},
	
	addAcceptHandler: function(fnHandler) {
		this.acceptControl.addEvent('click', fnHandler);
	},
	addCancelHandler: function(fnHandler) {
		this.cancelControl.addEvent('click', fnHandler);
	},
	
	addHideButton: function(button) {
		button.addEvent('click', this.hide.bind(this));
	},
	
	setAcceptText: function(aText) {
		this.acceptControl.setHTML(aText);
	},
	setCancelText: function(aText) {
		this.cancelControl.setHTML(aText);
	},
	
	//Estilos
	setDialogClass: function(className) {
		this.dialog.addClass(className);
	},
	setTitleClass: function(className) {
		this.dialogTitle.addClass(className);
	}
});

Dialog.NONE = 0;
Dialog.CLOSE = 1;
Dialog.MINIMIZE = 2
Dialog.ACCEPT = 4;
Dialog.CANCEL = 8;
Dialog.BACKGROUND = 16;
Dialog.TITLE = 32;

Dialog.CONFIRM = Dialog.ACCEPT | Dialog.CANCEL | Dialog.BACKGROUND | Dialog.TITLE;
Dialog.NORMAL = Dialog.CLOSE | Dialog.MINIMIZE | Dialog.BACKGROUND | Dialog.TITLE;
Dialog.ERROR = Dialog.ACCEPT | Dialog.BACKGROUND | Dialog.TITLE;
Dialog.AUTO = Dialog.BACKGROUND | Dialog.TITLE;
Dialog.NOTITLE = Dialog.BACKGROUND;

function addMinimizedDialog(aDialog) {
	var dialogIT;
	var elem;
	for (dialogIT = 0; elem = minimizedDialogs[dialogIT]; dialogIT ++) {
		if (elem == aDialog) {
			return false;
		}
	}
	
	var takenIT = 0;
	while (isTaken = positionsAvailable[takenIT]) {
		if (isTaken == -1) {
			positionsAvailable[takenIT] = 1;
			positionsTaken.push(takenIT);
			minimizedDialogs.push(aDialog);
			
			moveMinimizedDialog(aDialog, takenIT);
			return true;
		}
		takenIT ++;
	}
	
	return false;
}

function removeMinimizedDialog(aDialog) {
	var dialogIT;
	var elem;
	for (dialogIT = 0; elem = minimizedDialogs[dialogIT]; dialogIT ++) {
		if (elem == aDialog) {
			//Lo saca de la lista de minimizados
			minimizedDialogs.splice(dialogIT, 1);
			
			//Lo saca de la lista de posiciones
			var takenIT = positionsTaken[dialogIT];
			positionsAvailable[takenIT] = -1;
			positionsTaken.splice(dialogIT, 1);
			
			//Hace el efecto
			moveAllMinimizedDialogs(0);
			return true;
		}
	}
	
	return false;
}

function moveMinimizedDialog(aElem, elemPosition) {
	aElem.moveEffect.start({
		'bottom': (parseInt(elemPosition / 7) * 32),
		'left': ((elemPosition % 7) * 135),
		"margin-left": "0px",
		"margin-bottom": "0px"
	});
	aElem.lastEffect = now();
	aElem.effectDelay = 1000;
}

function moveAllMinimizedDialogs(initValue) {
	var dialogIT;
	var aElem;
	var moveAlls = minimizedDialogs.copy();
	var takenAlls = positionsTaken.copy();
	
	if (checkingMinimized) {
		var fx = function () {
			moveAllMinimizedDialogs()
		}.delay(100, this);
		return false;
	}
	
	checkingMinimized = true;
	for (dialogIT = initValue; aElem = moveAlls[dialogIT]; dialogIT ++) {
		if (aElem.dialogStatus != "minimized") {
			moveAllMinimizedDialogs(0);
			break;
		}
		
		moveMinimizedDialog(aElem, takenAlls[dialogIT]);
		
		if (aElem.dialogStatus != "minimized") {
			moveAllMinimizedDialogs(0);
			break;
		}
	}
	checkingMinimized = false;
}

function now() {
	var ret = $time();
	return ret;
}

