tinyMCE.init({
	mode : "specific_textareas",
	editor_selector : "editor",
	content_css : "/static/css/tinymce.css",
	theme : "advanced",
	language : "es",
	auto_focus : "text",
	plugins : "autolink,autoresize,lists,paste,spellchecker",
	relative_urls : false,
	
	theme_advanced_buttons1 : "bold,italic,|,blockquote,|,imagelink,videolink,|,videolink,outterlink,unlink,numlist,bullist,|,spellchecker",
	theme_advanced_buttons2 : "",
	theme_advanced_buttons3 : "",
	theme_advanced_toolbar_location : "top",
	theme_advanced_toolbar_align : "left",
	
	extended_valid_elements : "span[class],img[id|name|src],object[id|width|height],param[name|value],embed[width|height|src|flashvars|wmode|allowfullscreen|allowscriptaccess|type]",

	paste_auto_cleanup_on_paste : true,
	paste_preprocess : function(pl, o) {
		o.content = o.content.replace(/(\<)(?!br(\s|\/|\>))(.*?\>)/g, "");
    },
    
    spellchecker_languages : "+Castellano=es,Català=ca",
    spellchecker_rpc_url : "/spellchecker",
	
	setup : function(ed) {
		ed.addButton("outterlink", {
			title : "Enlace externo",
			image : "/static/images/icons/enlace_ext.png",
			onclick : function() {
				var selection = ed.selection.getContent();
				var text = selection.replace(/\<.*?\>/g, "");
				var from = selection.indexOf("href=\"http://");
				var to = selection.indexOf("\">", from);
				var url = "";
				if (from != -1) {
					url = selection.substring(from + 13, to);
				} else if (text.match(/^http\:\/\/\w+([\.\-]\w+)*\.\w{2,4}(\:\d+)*([\/\.\-\?\&\%\#]\w+)*\/?$/i)) {
					url = text.split("http://")[1];
				}
				openPopup(500);
				loadRefPopup("/articulo/nueva-referencia/externa?text=" + escape(text) + "&url=" + url);
			}
		});
		ed.addButton("imagelink", {
			title : "insertar foto",
			image : "/static/images/icons/editorImagen.png",
			onclick : function() {
				uploadAdvancedEditorPicture();
			}
		});
		ed.addButton("videolink", {
			title : "insertar vídeo",
			image : "/static/images/icons/editorVideo.png",
			onclick : function() {
				uploadEditorVideo();
			}
		});
		ed.addButton("innerlink", {
			title : "Enlace de 6cero",
			image : "/static/images/icons/enlace_int.png",
			onclick : function() {
				var selection = ed.selection.getContent();
				var text = selection.replace(/\<.*?\>/g, "");
				openPopup(500);
				loadRefPopup("/articulo/nueva-referencia/interna?text=" + escape(text));
			}
		});
		ed.onInit.add(function(ed) {
			setNewEditor();
			tinymce.dom.Event.add(ed.getWin(), "focus", function(e) { // gestión del foco
				if (!bookmark) { // si no hemos guardado el cursor...
					var selection = ed.selection;
					selection.select(getLastNode(ed)); // seleccionamos el último nodo
					selection.collapse(false); // y colocamos el cursor al final
				}
		    });
		});
		ed.onBeforeGetContent.add(function(ed, o) {
			var dom = ed.dom;
			dom.remove(dom.select(".firebugLayoutBox"));
			dom.remove(dom.select(".Apple-style-span"));
		});
		ed.onKeyDown.add(function(ed, e) {
			var code = e.keyCode, dom = ed.dom, selection = ed.selection;
			var currentNode = selection.getNode(); // ¡OJO! si se seleccionan dos nodos diferentes, currentNode es el ancestro común -> body
			if (tinymce.isWebKit && currentNode.nodeName == "BODY" && selection.isCollapsed()) { // si estamos en Chrome y currentNode es <body>...
				currentNode = selection.getSel().anchorNode;
				if (currentNode.nodeType == 3) { // si el nodo es de texto...
					currentNode = currentNode.parentNode; // seleccionamos el padre
				}
			}
			if (currentNode.nodeName == "BODY" && selection.isCollapsed()) { // si estamos intentando modificar <body>...
				currentNode = getNextNode(ed, currentNode); // seleccionamos el siguiente nodo (el primero del cuerpo)
				selection.select(currentNode); // y movemos la selección al principio de dicho nodo
				selection.collapse(true);
			}
			if (getMediaContainer(dom, currentNode)) { // si estamos intentando modificar el contenedor de una imagen o un vídeo...
				tinyMCE.dom.Event.cancel(e); // cancelamos el evento
			} else if (code == 8 || code == 46) { // backspace o suprimir
				if (selection.selectedRange) { // si existe "selectedRange"...
					range = selection.selectedRange;
				} else {
					range = selection.getRng();
				}
				var targetNode;
				if (code == 8 && range.startOffset == 0 && range.endOffset == 0) { // si borramos hacia atrás y estamos al principio del párrafo...
					targetNode = currentNode.previousSibling;
				} else if (code == 46 && range.startOffset == range.startContainer.length && range.endOffset == range.endContainer.length) { // hacia alante...
					targetNode = currentNode.nextSibling;
				}
				if (targetNode && dom.hasClass(targetNode, "insertionAdvancedContent")) { // si lo que vamos a borrar es una imagen o un vídeo...
					tinyMCE.dom.Event.cancel(e); // cancelamos el evento
					dom.remove(targetNode); // y eliminamos el nodo manualmente
				}
			}
		});
		ed.onMouseDown.add(function(ed, e) {
			var dom = ed.dom, targetNode = e.target;
			var forbiddenNode = getMediaContainer(dom, targetNode);
			if (e.target.nodeName != "P" && forbiddenNode) { // si se está haciendo click en el contenedor de una imagen o un vídeo (sin incluir las opciones del menú)...
				tinyMCE.dom.Event.cancel(e); // lo cancelamos
			}
		});
		ed.onClick.add(function(ed, e) {
			var dom = ed.dom, selection = ed.selection, targetNode = e.target;
			var imageMenu = dom.getParent(targetNode, "DIV.optionsImageEditor");
			if (targetNode.nodeName == "P" && imageMenu) { // si se ha hecho click en una opción del menú de imagen...
				var id = imageMenu.getAttribute("id");
				var className = targetNode.className;
				if (className == "delete") {
					deleteImaEditor(id);
				} else {
					if (className == "picLeft" || className == "picCenter" || className == "picRight") {
						changeImaEditorStyle(id, className);
					} else if (className == "large" || className == "medium" || className == "small" || className == "original") {
						changeImaEditorSize(id, className);
					}
				}
				restoreBookmark();
			} else {
				var forbiddenNode = getMediaContainer(dom, targetNode);
				if (forbiddenNode) { // si se ha hecho click en el contenedor de una imagen o un vídeo...
					selection.select(getNextNode(ed, forbiddenNode)); // seleccionamos el siguiente nodo
					selection.collapse(true); // y colocamos el cursor al principio
				}
			}
		});
		ed.onNodeChange.add(function(ed, cm, e) {
			var dom = ed.dom, selection = ed.selection;;
		    var numlist = cm.get("numlist");
		    var bullist = cm.get("bullist");
			var blockquote = cm.get("blockquote");
		    if (dom.getParent(e, "BLOCKQUOTE")) { // dentro de blockquote, deshabilitamos las listas
		    	blockquote.setDisabled(false);
	    		numlist.setDisabled(true);
	    		bullist.setDisabled(true);
		    } else if (dom.getParent(e, "LI")) { // dentro de las listas, deshabilitamos blockquote
		    	blockquote.setDisabled(true);
		    	numlist.setDisabled(false);
		    	bullist.setDisabled(false);
		    } else {
		    	numlist.setDisabled(false);
		    	bullist.setDisabled(false);
		    	blockquote.setDisabled(false);
		    }
		    var forbiddenNode;
			if (e.nodeName == "BODY") { // si nos hemos metido en <body>...
				forbiddenNode = e;
			} else {
				forbiddenNode = getMediaContainer(dom, e); // comprobamos si nos hemos metido en el contenedor de una imagen o un vídeo...
			}
			if (forbiddenNode) { 
				selection.select(getNextNode(ed, forbiddenNode)); // seleccionamos el siguiente nodo
				selection.collapse(true); // y colocamos el cursor al principio
			}
		});
	}
});

var bookmark;

function storeBookmark() {
	var ed = tinyMCE.activeEditor;
	bookmark = ed.selection.getBookmark(2); // Unobtrusive (http://tinymce.moxiecode.com/forum/viewtopic.php?pid=71854#p71854)
}

function restoreBookmark() {
	var ed = tinyMCE.activeEditor;
	ed.selection.moveToBookmark(bookmark);
}

function getLastTyped(ed, end_offset, delimiters, min_length) {
	var r, end, start, endContainer, text, matches, prev, len;
	r = ed.selection.getRng().cloneRange();
	if (min_length && r.startOffset < min_length) { // para buscar URLs -> longitud mínima esperada = min_length
		prev = r.endContainer.previousSibling;
		if (prev == null) {
			if (r.endContainer.firstChild == null || r.endContainer.firstChild.nextSibling == null) {
				return null;
			}
			prev = r.endContainer.firstChild.nextSibling;
		}
		len = prev.length;
		r.setStart(prev, len);
		r.setEnd(prev, len);
		if (r.endOffset < min_length) {
			return null;
		}
		end = r.endOffset;
		endContainer = prev;
	} else {
		endContainer = r.endContainer;
		if (endContainer.nodeType != 3 && endContainer.firstChild) { // buscamos un nodo de texto
			while (endContainer.nodeType != 3 && endContainer.firstChild) {
				endContainer = endContainer.firstChild;
			}
			r.setStart(endContainer, 0);
			r.setEnd(endContainer, endContainer.nodeValue.length);
		}
		if (r.endOffset == 1) {
			end = 2;
		} else {
			end = r.endOffset - 1 - end_offset;
		}
	}
	start = end;
	do { // vamos retrasando la selección carácter a carácter
		r.setStart(endContainer, end - 2);
		r.setEnd(endContainer, end - 1);
		text = r.toString();
		end -= 1;
	} while (!text.match(delimiters) && (end - 2) >= 0); // seguimos hasta que encontremos un delimitador o sólo queden 2 caracteres
	if (text.match(delimiters)) {
		r.setStart(endContainer, end);
		r.setEnd(endContainer, start);
		end += 1;
	} else if (r.startOffset == 0) {
		r.setStart(endContainer, 0);
		r.setEnd(endContainer, start);
	} else {
		r.setStart(endContainer, end);
		r.setEnd(endContainer, start);
	}
	return r;
}

function getLastNode(ed) {
	var dom = ed.dom, root = dom.getRoot();
	var lastNode;
	if (root.childNodes.length == 0) { // si no hay ningún nodo...
		lastNode = dom.add(ed.getBody(), "P", null, "<br />"); // creamos un <p><br /></p>
	} else {
		lastNode = root.childNodes[root.childNodes.length - 1]; // cogemos el último nodo
		if (tinymce.isGecko && lastNode.childNodes.length > 0) { // FF coloca el cursor fuera del último nodo
			lastNode = lastNode.childNodes[lastNode.childNodes.length - 1];
		}
		var forbiddenNode = getMediaContainer(dom, lastNode);
		if (forbiddenNode) { // si el último nodo es una imagen o un vídeo...
			lastNode = dom.add(ed.getBody(), "P", null, "<br />"); // creamos un <p><br /></p> detrás
		}
	}
	return lastNode;
}

function getNextNode(ed, currentNode) {
	var dom = ed.dom;
	var nextNode;
	if (currentNode.nodeName == "BODY") {
		nextNode = getFirstPNode(dom);
	} else {
		nextNode = currentNode.nextSibling;
	}
	if (!nextNode) { // si no hay ningún nodo detrás...
		nextNode = dom.add(ed.getBody(), "P", null, "<br />"); // creamos un <p><br /></p> al final
	} else if (dom.hasClass(nextNode, "insertionAdvancedContent")) { // si el siguiente nodo es un contenedor de imagen o vídeo...
		nextNode = getNextNode(ed, nextNode); // buscamos el siguiente nodo (y así sucesivamente)
	}
	return nextNode;
}

function getFirstPNode(dom) {
	var pNodes = dom.select("P");
	for (var i in pNodes) {
		var pNode = pNodes[i];
		if (!dom.getParent(pNode, "DIV.insertionAdvancedContent")) {
			return pNode;
		}
	}
}

function getMediaContainer(dom, currentNode) {
	if (dom.hasClass(currentNode, "insertionAdvancedContent")) {
		return currentNode;
	}
	return dom.getParent(currentNode, "DIV.insertionAdvancedContent");
}

function saveContent() {
	tinyMCE.each(tinyMCE.editors, function(ed) {
		var spellchecking = ed.plugins.spellchecker.active;
		var cursor = ed.selection.getBookmark();
	    var content = ed.getBody().innerHTML; // contenido "sucio" del editor
	    ed.save(); // guarda el contenido "limpio" en el textarea
		ed.setContent(content, {format : "raw"}); // reestablece el contenido "sucio" en el editor
		ed.selection.moveToBookmark(cursor);
		ed.plugins.spellchecker.active = spellchecking; // reactiva el corrector ortográfico (si estaba activo)
		ed.nodeChanged();
	});
}

