// Chris Pyper 2006
// Functions for manipulation of content

// Fetch content
function getContent(mode)
{
	debug('getContent()', 'info');

	var turnBackOn = false;

	if(editorOn && !mode && mode != "timed")
	{
		debug('getContent() - Toggling editor OFF to fetch content', 'warn');
		turnBackOn = true;
		stopEditor();
	}
	
	if(!document.getElementById(INNEREDITORID))
	{
		debug('getContent() - Error cannot fetch element id: ' + INNEREDITORID, 'error');
		return false;
	}

	var content =  document.getElementById(INNEREDITORID).innerHTML;

	if(turnBackOn)
		startEditor();

	return content;
}

// Set content
function setContent(content)
{
	debug('setContent()', 'warn');

	var turnBackOn = false;

	if(editorOn)
	{
		debug('setContent() - Toggling editor OFF to set content', 'warn');
		turnBackOn = true;
		stopEditor();
	}

	if(!document.getElementById(INNEREDITORID))
	{
		debug('setContent() - Error cannot fetch element id:' + INNEREDITORID, 'error');
		return false;
	}

	document.getElementById(INNEREDITORID).innerHTML = content;

	if(turnBackOn)
		startEditor();

	return true;
}
function fixHoverForIE6()
{
	if (!/MSIE (5\.5|6)/.test(navigator.userAgent) || typeof filters == 'unknown') return;
	try{
		parseStylesheets();
	}catch(e){}
}

// Add background template
function setTemplate(content)
{
	debug('setTemplate()', 'warn');
	
	var turnBackOn = false;

	if(editorOn)
	{
		debug('setTemplate() - Toggling editor OFF to set template', 'warn');
		turnBackOn = true;
		stopEditor();
	}

	document.body.innerHTML = content;

	// Search for a element with the defined ID and replace it with the three required editor tags
	if(document.getElementById(BODYID))
	{
		divOut = document.createElement("div");
		divOut.id = OUTEREDITORID;

		divMid = document.createElement("div");
		divMid.id = MIDDLEEDITORID;

		divIn = document.createElement("div");
		divIn.id = INNEREDITORID;

		divMid.appendChild(divIn);
		divOut.appendChild(divMid);
	
		var docRef = document.getElementById(BODYID);
		docRef.parentNode.replaceChild(divOut, docRef);
	}
	else
		return false;

	if(turnBackOn)
		startEditor();

	return true;
}

// Add style sheet, this may require a reload to call more then once, there are no remove stylesheet methods
function setStyleSheet(url)
{
	debug('setStyleSheet()', 'info');

	var turnBackOn = false;
	
	if(editorOn)
	{
		debug('setStyleSheet() - Toggling editor OFF to set stylesheet', 'warn');
		turnBackOn = true;
		stopEditor();
	}

	var ret = document.styleSheets[0].addImport(url);

	if(turnBackOn)
		startEditor();

	return ret;
}

// Add a element to the editor
function addElement(docRef, top, left, undoRedo, internalCall)
{
	debug('addElement()', 'info');

	if(!editorOn)
	{
		debug('addElement() - Error editor must be on to add element', 'warn');
		return false;
	}

	if(!docRef)
	{
		debug('addElement() - No Element specified', 'error');
		return false;
	}

	if(docRef.nodeType != 1 /*Node.ELEMENT_NODE*/)
	{
		debug('addElement() - Element is not a element node', 'error');
		return false;
	}

	if(!document.getElementById(INNEREDITORID))
	{
		debug('addElement() - Cannot find node by id INNEREDITORID', 'error');
		return false;
	}

	// IE won't clone another node that is referenced in a iframe properly, in the case of a undoRedo it is internal
	// so we can use the DOM method cloneNode, it is not effected by the iframe issue.
	if(!ie || undoRedo || internalCall)
		var clone = docRef.cloneNode(true);
	else
	{
		// IE won't clone another node that is referenced in a iframe properly, so we make our own clone
		var clone = document.createElement(docRef.tagName);

		if(docRef.innerHTML)
			clone.innerHTML = docRef.innerHTML;

		// A list of the attributes to copy over
		// ***FIXME*** We need a way to replicat style, right now it return an object not a string so it does not work
		//It's should work for IE style
		clone.style.cssText = docRef.style.cssText;

		var attributes = new Array("name", "id", "className", "style", "src", "width", "height", "ESWID", "onclick", "onload", "alt","img_href", "custom_page");
		for(var i=0; i<attributes.length; ++i)
		{
			var attribute = docRef.getAttribute(attributes[i], 0);
			if(attribute)
				clone.setAttribute(attributes[i], attribute, 0);
			else
				debug("addElement() - attribute not found, skipping : " + attributes[i], 'info');
		}

	}
	if(top)
		setStyle(clone, 'top', top, true);
	if(left)
		setStyle(clone, 'left', left, true);
	generateId(clone);
	if (masterMode)
		clone.setAttribute(MASTER_EL_ATTR, "true");

	var docRefId = getId(clone);
	document.getElementById(INNEREDITORID).appendChild(clone);
	var docRef = getElementByESWId(docRefId);
	raiseToTop(docRef);
	if(!undoRedo)
		undoRedoSnapShot(docRef, 'add');
	setStyle(docRef, 'visibility', 'visible');

	// show a little border animation to draw attention to the new element
	if ( docRef.className.indexOf("Plugin") < 0 )
	{
		flashElement(docRef);
	//		setTimeout( function() { setStyle(docRef,'border','2px dotted #0289E1'); }, 100 );
	//		setTimeout( function() { setStyle(docRef,'border','none'); }, 250 );
	//		setTimeout( function() { setStyle(docRef,'border','2px dotted #04B9FF'); }, 350 );
	//		setTimeout( function() { setStyle(docRef,'border','none'); }, 500 );
	}

	documentChanged = true;
	return docRefId;
}

function deleteElement(docObj, undoRedo)
{
	debug('deleteElement()', 'info');

	var delDocRef = getElementByESWId(getId(docObj));

	if(delDocRef)
	{
		// Take undo/redo snapshot
		if(!undoRedo)
			undoRedoSnapShot(delDocRef, 'delete');

		// Remove from DOM tree
		delDocRef.parentNode.removeChild(delDocRef);
	}
	else
	{
		debug('deleteElement() Error id/name not found, cannot delete', 'error');
		return false;
	}

	documentChanged = true;

	return true;
}

function changeElementId(oldId,newId)
{
	var el = getElementByESWId(oldId);

	if ( el )
	{
		debug("changeElementId(): " + oldId + " becomes " + newId, "info");
		el.id = newId;
		return newId;
	}
	else
	{
		debug("changeElementId(): element not found: " + oldId, "error");
		return oldId;
	}

}

// Edit an element with an external editor
function externalEditSelectedElement(e)
{
	debug("externalEditSelectedElement()", 'info');

	if(!docSourceClone)
	{
		debug('externalEditSelectedElement() no element selected', 'warn');
		return false;
	}

	var docObj = getDocObjFromClone();

	if ( EXTERNAL_EDITORS[docObj.tagName] )
	{
		EXTERNAL_EDITORS[docObj.tagName](docObj);

		documentChanged = true;
		return true;
	}
	else
	{
		debug('No external editor defined for ' + docObj.tagName + ' tag.', 'warn');
		return false;
	}

}


// Delete the object selected for editing
function deleteSelectedElement(e)
{
	debug("deleteSelectedElement()", 'info');

	if(!docSourceClone)
	{
		debug('deleteSelectedElement() no element selected', 'warn');
		return false;
	}

	var docObj = getDocObjFromClone();

	// Shut her down
	if(docSourceClone)
		designModeOff();

	return deleteElement(docObj);
}


// Duplicate the object selected for editing
function duplicateSelectedElement()
{
	debug("duplicateSelectedElement()", 'info');

	if(!docSourceClone)
	{
		debug('duplicateSelectedElement() no element selected', 'warn');
		return false;
	}

	// Clean up spell check if it is on
	removeSpellCheckHighlighting();
	document.getElementById('spellCheck').innerHTML = '';

	var docObj = getDocObjFromClone();

	// Shut her down
	if(docSourceClone)
		designModeOff();


	// content editable off patch for dup in IE
	if (ie)
		docObj.contentEditable = false;

	// Force generation of new unique id
	generateId(docObj, true);


	// Calculate new offset
	var top  = getStyle(docObj, 'top', true);
	var left = getStyle(docObj, 'left', true);

	return addElement(docObj, top + DUPLICATEOFFSET, left + DUPLICATEOFFSET, false, true);
}

// Cache for selcetion and ranges to maintain highlighting between possible focus change of link editing procedure
var cachedLinkRange	= null;

// Begin hyperlink creation progress, receive signal from interface and return reference to existing link if
// cursor or hightlight is placed on it, otherwise take hightlightted text and create blank link object based 
// upon it. Using link object maintains a consistent DOM based interface.
function createLink() 
{
	debug("createLink()", 'info');

	var link = getParentElement();

	// if element is an image, move up the tree one tag
	if (link && /^img$/i.test(link.tagName))
		link = link.parentNode;
	if (link && !/^a$/i.test(link.tagName))
	{
		debug("createLink() No link, found tag: " + link.tagName, 'info');
		link = null;
	}

	// Cache for unfocus, creating and editing links is a two setp process
	cachedLinkRange = getRange(getSelection());

	var callBacks = fetchInterface();
	// Make call back to determnie edited link parameters, use existing or create if does not exist
	// pass over entire node to maintain consistent DOM node based interface to editor
	if(link)
		callBacks.triggerCallBack('linkCreate', link);
	else
	{
		var linkStub = document.createElement("a");
		linkStub.innerHTML = getSelectionText();
		callBacks.triggerCallBack('linkCreate', linkStub);
	}

	return true;
}

function receiveLink(linkObj)
{
	debug("receiveLink()", 'info');
	
	// Select previously highlighted content. creating and editing links is a two step process, this is done
	// in case of shift in focus on button click
	cachedRange	= cachedLinkRange;

	// Make sure it is highlighted
	highlightSelection();

	var link = getParentElement();

	// if element is an image, move up the tree one tag
	if (link && /^img$/i.test(link.tagName))
		link = link.parentNode;
	if (link && !/^a$/i.test(link.tagName))
	{
		debug("createLink() No link, found tag: " + link.tagName, 'info');
		link = null;
	}

	var a = link;
	if (!a)
	{
		if(ie)
		{
			// Build it
			execCommand("createlink", false, linkObj.href);

			a = getParentElement();
			var sel = getSelection();
			var range = createRange(sel);
			if (!ie)
			{
				a = range.startContainer;
				if (!/^a$/i.test(a.tagName))
					a = a.nextSibling;
			}
			a.target    = linkObj.target;
			a.title     = linkObj.title;

		}
		else
		{
			// The selection is not preserved in Gecko based browers, we could do this but it would give the
			// user the impression they can maipulate it, however they can't because fosus is lost during
			// the link creation process, thus to higlight it again we must use javascript, which under
			// mozilla means certain functionaliyt will not work on javascript generated ranges and selections.

			a = document.createElement('a');
			a.href   = linkObj.href;
			a.target = linkObj.target;
			a.title  = linkObj.title;

			// ***WARNING EXTREMELY IMPORTANT***
			// This is the final result of much pain and suffering.  When an object is highlighted by javascript, not
			// by the user itself, you cannot execCommand() on the range.  Various other function in the range object
			// such as surroundContents() also do not work.  They all throw very bad exceptions or crash the browser.
			// the only way I have discovered to manipulate selection or text ranges created by javascript, not by the
			// user highlighting, was to use the few methods that did work.  I don't know if those methods alwaays
			// did not work, after all the browser is open source, but this works.
			try
			{
				var range = createRange(createSelection());

				a.innerHTML = range.toString();

				range.deleteContents();
				range.insertNode(a);

			// Gecko sucks balls, the link creation process fucks something up so nothing works right after in the
			// design mode frame, after some messing around it is discovered that toggling on and off design mode
			// on the iframe fixes this
			//iframe.contentWindow.document.designMode = "off";
			//iframe.contentWindow.document.designMode = "on";
			//var frameId = docSourceOrig.id;
			//designModeOff();
			//designModeOn(document.getElementById(frameId));

			// Looks like the issue above is no more with the Firefox 2.x series... commented out the
			// above 2 lines. Pyper's comment preserved for posterity. :)  -- jwm
			}
			catch(e)
			{
				debug("receiveLink() - EXCEPTION THROWN !!!", "error");
			}

		}
	}
	else
	{
		// Modify existing
		a.href = linkObj.href;
		a.target = linkObj.target;
	}
	a.setAttribute(LINK_HREF_ATTR, linkObj.getAttribute(LINK_HREF_ATTR)); // patch for non cklicable links
	a.href = "#"; // patch for non cklicable links
	a.onclick = function(e){
		e=(window.event || e); if(!e) return; if(e.preventDefault)e.preventDefault(); e.returnValue=false;
	};


	return true;
}

// Plugins are represented as DIVs which wrap an IFRAME which hosts the plugin
function insertPlugin(pluginName)
{

	debug("insertPlugin(): " + pluginName, "info");

	var pluginContainer = document.createElement("div");
	var pluginLabel = document.createElement("div");
	var pluginLabelText = document.createElement("span");
	var pluginFrame = document.createElement("iframe");
	var pluginDeleteBtn = document.createElement("button");
	
	pluginContainer.className = "editorPlugin draggable";

	pluginLabel.className = "editorPluginLabel";
	pluginLabelText.className = "editorPluginLabel";
	pluginLabelText.appendChild(document.createTextNode(translate("Configure")));
	pluginLabelText.setAttribute("onclick", "configPlugin(this.parentNode.parentNode.lastChild)", 0);
	//	pluginLabelText.setAttribute("style", "", 0);
	pluginDeleteBtn.className = "darkButton";
	pluginDeleteBtn.setAttribute("style", "bottom: 5px; left:5px; position:absolute; width:6px;", 0);
	pluginDeleteBtn.style.cssText = 'bottom: 5px; right:5px; position:absolute;';

	pluginDeleteBtn.appendChild(document.createTextNode("X"));
	pluginLabel.appendChild(pluginLabelText);
	generateId(pluginFrame);
	pluginFrame.className = "editorPluginView";
	
	pluginFrame.setAttribute("src", "plugins/" + pluginName + "/view.html?id="+getId(pluginFrame) + "&lang=" + EDITORUSERLANGUAGE, 0);
	pluginFrame.setAttribute("pluginname", pluginName);
	pluginFrame.setAttribute("scrolling","no");
	pluginContainer.appendChild(pluginLabel);
	//	pluginContainer.appendChild(pluginDeleteBtn);
	pluginContainer.appendChild(pluginFrame);

	//generateId(pluginContainer);

	var res = addElement(pluginContainer, 300, 200, false, false);
	
	//pluginDeleteBtn.setAttribute("onclick", "deleteElement('" + res + "')", 0);
	//	getEl(getId(pluginFrame)).previousSibling.onclick = function(){deleteElement('" + res + "')};
	return res;
}

function resizePlugin(pluginFrameId)
{
	// Trim any special character from the beginning of the ID
	// Since this function may be called from a plugin iframe who is
	// passing the id from the "hash" portion of its location url,
	// the first character will usually be '#'
	//if ( !pluginFrameId.substring(0,1).match(/[a-z]|[A-Z]/) )
	//	pluginFrameId = pluginFrameId.substring(1,pluginFrameId.indexOf('?')); // everything between # and ?

	var pluginFrame = document.getElementById(pluginFrameId);

	// Resize the iframe
	pluginFrame.style.width = pluginFrame.contentWindow.pluginObject.getPreferredWidth() + "px";
	pluginFrame.style.height = pluginFrame.contentWindow.pluginObject.getPreferredHeight() + "px";
	
	// And resize the plugin container
	if (pluginFrame.parentNode.firstChild.offsetHeight)
		pluginFrame.parentNode.style.height = parseInt(pluginFrame.style.height) + pluginFrame.parentNode.firstChild.offsetHeight;
	else
		pluginFrame.parentNode.style.height = pluginFrame.style.height;
	pluginFrame.parentNode.style.width = pluginFrame.style.width;

}

function configPlugin(pluginFrame)
{
	if(pluginFrame && pluginFrame.contentWindow && pluginFrame.contentWindow.pluginObject)
	{
		try
		{
			var name = pluginFrame.contentWindow.pluginObject.getName();
	
			// alert('configPlugin: ' + pluginFrame.id);

			if ( pluginFrame.src.indexOf("conf.html") > 0 )
			{
				pluginFrame.style.opacity = "1.0";
				pluginFrame.src = "plugins/" + name + "/view.html?id=" + pluginFrame.id + "&lang=" + EDITORUSERLANGUAGE;
			}
			else
			{
				pluginFrame.style.opacity = "0.9";
				pluginFrame.src = "plugins/" + name + "/conf.html?id=" + pluginFrame.id + "&lang=" + EDITORUSERLANGUAGE;
			}
			return pluginFrame.src;
		}
		catch(e){}
	}
	return null;
}

// edit image properties

function editSelectedImageProperties(e)
{
	debug("editImageProperties()", 'info');

	if(!docSourceClone)
	{
		debug('editSelectedImageProperties() no element selected', 'warn');
		return false;
	}

	var docObj = getDocObjFromClone();

	// Shut her down
	if(docSourceClone)
		designModeOff();

	var callBacks = fetchInterface();
	callBacks.triggerCallBack('openImageProperties', docObj);
	return true;
}

function applySelectedImageProperties(id, img_href, alt, new_wind, bStyle)//, bWidth, bColor )
{

	var imgObjId = document.getElementById(id);

	if (imgObjId == null)
		return false;

	var imgObj = document.getElementById(id);
	if (imgObj == null)
		return false;


	imgObj.setAttribute("alt", alt);
	imgObj.setAttribute("img_href", img_href);
	imgObj.setAttribute("new_wind", new_wind);
	imgObj.style.border = bStyle;
	//imgObj.style.borderColor = bColor;
	//imgObj.style.borderWidth = bWidth;
	return true;
}

// edit table props
function editSelectedTableProperties(e)
{
	debug("editSelectedTableProperties()", 'info');

	if(!docSourceClone)
	{
		debug('editSelectedTableProperties() no element selected', 'warn');
		return false;
	}

	var docObj = getDocObjFromClone();


	var callBacks = fetchInterface();
	callBacks.triggerCallBack('openTableProperties', docObj);
	return true;
}

function applySelectedTableProperties(id, div)
{
	var contObj = document.getElementById(id);

	if (contObj == null)
		return false;

	contObj.innerHTML = div.innerHTML;
	// ADD ADDITIONAL STYLES
	contObj.style.height = div.style.height;
	contObj.style.width = div.style.width;
	var table = contObj.firstChild;
	if (table)
	{
		if ( table.tagName == "TABLE" )
		{
			var h = table.clientHeight;
			var cH = contObj.style.height.replace("px", "");
			if ((h - cH)> 10)
				contObj.style.height = h +5 +"px"; 
		}
	}
	
	return true;
}


//Line interval stuff
function getSelectedBlocks ()
{
	function moveToParent(node, parent)
	{
		while((node && !(node.parentNode && node.parentNode.tagName && node.parentNode.tagName.toLowerCase() == 'div')))
		{
			node = node.parentNode;
		}
		return node;
	}

	debug("getSelectedBlocks()", 'info');

	var start, end;
	var arr = false;
	var parent = docSourceClone;
	var range = createRange(createSelection());

	if(!range)
		return false;
	if(ie)
	{
		function getEndPoint(start)
		{
			try {
			var rng = range.duplicate();
			rng.collapse(start);
			return rng.parentElement();
			}catch(e){}
		}
		start  = getEndPoint(true);
		end  = getEndPoint(false);
	}
	else
	{
		start = range.startContainer;
		end = range.endContainer;
	}
	start = moveToParent(start, parent);
	end = moveToParent(end, parent);
	start = start ? start : docSourceClone.firstChild;
	end = end ? end : docSourceClone.lastChild;
	var node = start;
	if(node)
	{
		arr = [];
		do
		{
			arr.push (node);
			node = node.nextSibling ? node.nextSibling : null;
		}while(node && node.previousSibling != end)
	}
	return arr;

}
function setLineInterval (val)
{
	debug("setLineInterval()", 'info');
	var blocks = getSelectedBlocks();
	var idx = null;
	if(blocks)
	{
		for (idx in blocks)
		{
			try
			{
				var node = blocks[idx];
				node.style.lineHeight = ((val=='0')?"":val);
			} catch(e){};
		}
	}
	return true;
}

function getLineInterval ()
{
	debug("getLineInterval()", 'info');
	var sel = getSelection();
	var range = getRange(sel);
		
	var blocks = getSelectedBlocks();
	var idx = null;
	var ret = 0;
	if(blocks)
	{
		for (idx in blocks)
		{
			try
			{
				var node = blocks[idx];
				if(node.style && typeof node.style.lineHeight!= 'undefined')
				{
					ret = node.style.lineHeight;
					break;
				}
			} catch(e){};
		}
	}
	debug("getLineInterval: " + ret, 'info');
	return ret;
}
function pasteText()
{
    var text = top.getEl('pasteTextArea').value;
    if (text.length == 0)
        return false;
    text = text.replace("&","&amp;");
    text = text.replace(/</g,"&lt;");
    text = text.replace(/>/g,"&gt;");
    text = text.replace(/\r?\n/g,"<br>");
    if ( top.is_MSIE )
    {
		highlightSelection();
		var sel = createSelection();
		var rng = createRange(sel);
		rng.pasteHTML( text );
    }
    else
    {
        execCommand("insertHTML",false,text);
    }
	top.hideIt('pasteText');
	top.hideDimmer();
	return true;
}
function getTableData(p1, type)
{
	if (type == "style")
	{
		return  getStyleSheet("eswstyle.css");
	}
	var tds;
	var td;
	var el;
	var cont  = getEl(p1);
	var tables = cont.getElementsByTagName("table");
	if (tables.length)
		table = tables[0];
	else
		return false;
	if (type == "td" || type == "tdHeight")
	{
		var tds = table.getElementsByTagName("td");
		if (tds.length)
			td = tds[0];
		el = td;	
	}
	else
		el = table;
	if (type == "tdHeight")
	{

		var h = 0;
		var rows = table.getElementsByTagName("tr");
		if (rows.length)
		{
			for(var r=0;r<rows.length;r++)
			{
				var td = rows[i].firstChild;
				h += td.clientHeight;
			}
		}
		return h;
	}
	delete tds;
	delete td;
	delete cont;
	delete tables;
	return window.getComputedStyle(el, ""); 
}
