/**
 * @file
 * Javascript utility functions
 * Features
 * - obj2String: attempts to automatically output all the public fields of a
 *   javascript object to a string. Originally intended for use in an alert(),
 *   so fields are truncated in length and number.
 * - GeneralException: a convenient way to throw an exception. Throw this
 *   as the exception object. Holds an exception message, and optionally a
 *   related object. The inherited toString() method is overridden to return
 *   the message and the fields of the object where possible, so that the
 *   object can be used directly whereever a string is expected eg in an
 *   alert().
 *
 * @author Simon Li
 * @date 2005-03-31
 * $Id: utils.js 1369 2006-05-30 15:25:20Z alain $
 */


// Random javascript utility functions.

// An object containing static methods to help with formatting error or other
// diagnostic messages, etc.
var ObjectFormatter = {
	// Converts a javascript object into a string with each public field=value
	// on a separate line. Intended for debugging purposes.
	// @param o the object
	// @return the string
	obj2String: function (o) {
		
		var argv=arguments;
		var argc=arguments.length;
		var _depth = (argc > 1) ? argv[1] : 0;
		//alert (_depth);
		_depth++;
		//alert (_depth);
		
		// Parameters
		// Max length of a field value
		var maxLen = 10000;
		// Max number of fields to output
		var maxFields = 100;
		
		var s = new String();
		var n = 0;
		
		for (var fe in o) {
			for (var i=0;i<_depth;i++)
			{
				s += "    ";
			}
			try {
				var result = ObjectFormatter.formatLongString(o[fe], maxLen, true);
			
				s += fe + "=" + result + "\n";
				
				// Yes, this adds an extraneous newline to the end. Sod it.
			}
			catch (e) {
				s += fe + ":Exception getting field:" + e + "\n";
			}
			
			if (++n > maxFields) {
				s += "...\n";
				break;
			}
		}
		
		return s;
		
		//return "to do";
	},
	
	// Formatting function for long string
	// truncates a string and replaces newlines with a space
	// @param str the string
	// @param len max length of output string
	// @param rep if true newlines are replaced
	// @return the formatted string
	formatLongString: function (str, len, rep) {
		var input = new String(str);
		var result = new String();
		if (input.length > len) {
			input = input.substr(0, len) + "...";
		}
		
		// Now replace any newlines with a space
		if (rep) {
			for (var i = 0; i < input.length; ++i) {
				var c = input.charAt(i);
				if (c== "\n" || c == "\r") {
					result += " ";
				}
				else {
					result += c;
				}
			}
		}
		else {
			result = input;
		}
		
		return result;
	}
}

// An object containing static methods to help with setting an error message
// handler.
var DocumentErrorHandler = {
	// Produces an alert dialog containing the browser supplied error
	// information. This should be set as the document onerror handler
	// @param msg the error message
	// @param url the url containing the error
	// @param line the line where the error occurred
	alertError: function (msg, url, line) {
		var s = "ERROR: " + msg
			+ "\nurl: " + url
			+ "\nline: " + line;
		alert(s);
	},
	
	// Sets the document error handler (window.onerror)
	// @param pf function pointer to the error handler, defaults to
	//        DocumentErrorHandler.alertError() if not provided
	enableHandler: function (pf) {
		if (!pf) {
			pf = DocumentErrorHandler.alertError;
		}
		window.onerror = pf;
	},
	
	// Disables the current document error handler
	disableHandler: function () {
		window.onerror = null;
	}
}


// Constructor for an exception with a message and object
// @param m the message
// @param o the related object (optional)
function GeneralException(m, o) {
	// Auto recover from failure to use the new when cal;ling constructor
	if (!(this instanceof GeneralException)) {
		return new GeneralException(m, o);
	}
	
	// Pointer to self
	var m_self = this;
	// Was an object provided?
	var m_objValid = false;
	// Max length of one of the object field values
	var m_maxFieldValueLen = 60;
	
	// The exception message
	this.msg = m;
	
	if (arguments.length > 1) {
		// The associated object
		this.obj = o;
		m_objValid = true;
	}
	
	// The toString function
	GeneralException.prototype.toString = function () {
		var s = "EXCEPTION: " + m_self.msg + "\n";
		if (m_objValid) {
			s += "object: "
				+ ObjectFormatter.formatLongString(m_self.obj, m_maxFieldValueLen, true);
				+ "\n" + ObjectFormatter.obj2String(m_self.obj);
		}
		return s;
	}
	
	// Avoids a strict js warning in mozilla
	return this;
}

// An object containing static methods to help with formatting strings
var StringFormatter = {
	// Padding function
	// Adds the specified padding character to the beginning of a string to bring
	// it up to the specified minimum length
	// @param str the string to be padded
	// @param len the required minimum length of the string
	// @param pad the padding character
	// @return the padded string
	padBeginning: function (str, len, pad) {
		var result = new String(str);
		while (result.length < len) {
			result = pad + result;
		}
		return result;
	}
}


var Browser = {
	/*
	var details=navigator.userAgent;
	
	//Check for Mozilla browsers
	if(browser == "Netscape" && (details.indexOf("Gecko")!=-1) && (details.indexOf("Netscape")==-1)) 
		{browser="Mozilla"};
	
	//Check for Opera 5 browsers
	if (details.indexOf("Opera") !=-1) 
		{browser="Opera"};
	*/	
	isNS : function () {
		return (navigator.appName == "Netscape");
	},
		
	isIE : function () {
		return (navigator.appName == "Microsoft Internet Explorer");
	}
}


function ET_getSelection (node)
{
	if (tinyMCE.selectedInstance.getDoc().getSelection)	{
		return tinyMCE.selectedInstance.getDoc().getSelection();
	}
	else if (tinyMCE.selectedInstance.getDoc().getSelection){
		return tinyMCE.selectedInstance.getDoc().getSelection();
	}
	else if (tinyMCE.selectedInstance.getDoc().selection){
		return tinyMCE.selectedInstance.getDoc().selection.createRange().text;		
	}
	else return null;
}


var ET_TextArea = {
	insertAtCursor : function(myField, myValue) {
		//LOGDEBUG("insertAtCursor");
	  //IE support
		if (document.selection) {
			LOGDEBUG("SELECTION");
			//compulsory? --- myField.focus();
			//in effect we are creating a text range with zero
			//length at the cursor location and replacing it
			//with myValue 
			//LOGDEBUG("YO");
			var sel = document.selection.createRange();
			//LOGDEBUG("ssselectionStart:"+document.selectionStart);
			//LOGDEBUG("sssselectionEnd:"+document.selectionEnd);
			sel.text = myValue;
			
		}
		//MOZILLA/NETSCAPE support
		else if (myField.selectionStart || myField.selectionStart == '0') {
			//Here we get the start and end points of the
			//selection. Then we create substrings up to the
			//start of the selection and from the end point
			//of the selection to the end of the field value.
			//Then we concatenate the first substring, myValue,
			//and the second substring to get the new value. 
			var startPos = myField.selectionStart;
			var endPos = myField.selectionEnd;
			myField.value = myField.value.substring(0, startPos)
						  + myValue 
						  + myField.value.substring(endPos, myField.value.length);
		} else {
			myField.value += myValue;
		}
	},
	
	caretPos : function(myField){
		//LOGDEBUG("No selection:");
		var i=myField.value.length+1;
		if (myField.createTextRange){
			var theCaret = document.selection.createRange().duplicate();
			//LOGDEBUG("theCaret.text:"+theCaret.text);
			//LOGDEBUG("theCaret.parentElement():"+theCaret.parentElement());
			//LOGDEBUG("myField:"+myField);
			var t = theCaret.move("character",1);
			//LOGDEBUG("t:"+t);
			
			while ( theCaret.parentElement() == myField && theCaret.move("character",1)==1 ) --i;
		}
		//LOGDEBUG("i:"+i);
		return i==myField.value.length+1?-1:i;
	},
	
	// textarea is DOM object textarea
	// alternatedata. Sometime data od the text area are not directly accesible and we need to pass trow an other object
	currentCursorPosition : function (textarea) {
		
		var argv=ET_TextArea.currentCursorPosition.arguments;
		//LOGDEBUG("argv[0]:"+ObjectFormatter.obj2String(argv[0]));
		//LOGDEBUG("argv[1]:"+ObjectFormatter.obj2String(argv[1]));
		var argc=ET_TextArea.currentCursorPosition.arguments.length;
		//LOGDEBUG("argc:"+argc);
		var dataObject=(argc > 1) ? argv[1] : null;
		
	
	
		// if browser is FIREFOX it is easy
		
		if (Browser.isNS()) {
			// DOESN' WORK IN TINEME. DON'T KNOW WHY
		
			//LOGDEBUG("textarea:"+textarea);
			//LOGDEBUG("selectionStart:"+textarea.selectionStart);
			//LOGDEBUG("selectionEnd:"+textarea.selectionEnd);
			//	return textarea.selectionStart;
			return -2;
		}
		// if browser id IE
		else if (Browser.isIE()) {
			// return the first position of the selection if it exists
			var ret = ET_TextArea.caretPos(textarea);
			//LOGDEBUG("ret:"+ret);
			if (ret != -1) return ret;
			//return -1;
			
			else { // no selection so try another methode
				// add special tag at the current position
				var tag = '_ETAG_';
				ET_TextArea.insertAtCursor(textarea, tag);
	
				var sel = tinyMCE.selectedInstance.getBody();
				var pos;
				if (dataObject) {
					//LOGDEBUG("dataObject:"+dataObject);
					// look at its position
					pos = dataObject.innerHTML.search(tag);
					// delete the tag
					dataObject.innerHTML = dataObject.innerHTML.replace(tag,'');
				}
				else {
					
					//LOGDEBUG("textarea:"+textarea);				
					// look at its position
					pos = textarea.value.search(tag);
					// delete the tag
					textarea.value = textarea.value.replace(tag,'');
				}
				//LOGDEBUG("pos:"+pos);
				return pos;
			}
			
		}
		else return -1;
		
	}
}
function swap_images(img, obj){
				obj.src=img;
			}
