// Constants
var CONST_IDENT = '    ';
var CONST_NL = "\n";

var CONST_CHARCODE_B = 98;
var CONST_KEYCODE_B = 66;
var CONST_CHARCODE_R = 114;
var CONST_KEYCODE_R = 82;
var CONST_CHARCODE_S = 115;
var CONST_KEYCODE_S = 83;
var CONST_KEYCODE_TAB = 9;
var CONST_KEYCODE_ENTER = 13;

var timer = null;

function controlsSetBold(textField) {insertAtCaret(textField, '[b]', '[/b]');}

function controlsSetItalic(textField) {insertAtCaret(textField, '[i]', '[/i]');}

function controlsSetUnderline(textField) {insertAtCaret(textField, '[u]', '[/u]');}

function controlsSetLink(textField) {insertAtCaret(textField, '[link]http://', '[/link]');}

function controlsSetBreak(textField) {insertAtCaret(textField, '', '[br/]');}

	function controlsSetSmile(textField) {insertAtCaret(textField, '', ':-)');}
	function controlsSetLaught(textField) {insertAtCaret(textField, '', ':-D');}
	function controlsSetGlases(textField) {insertAtCaret(textField, '', '8-)');}
	function controlsSetOneEye(textField) {insertAtCaret(textField, '', ';-)');}
	function controlsSetTongue(textField) {insertAtCaret(textField, '', ':-P');}
	function controlsSetSick(textField) {insertAtCaret(textField, '', ':-S');}
	function controlsSetKiss(textField) {insertAtCaret(textField, '', ':-*');}
	function controlsSetWow(textField) {insertAtCaret(textField, '', ':-O');}
	function controlsSetNeutral(textField) {insertAtCaret(textField, '', ':-|');}
	function controlsSetSilent(textField) {insertAtCaret(textField, '', ':-X');}
	function controlsSetSad(textField) {insertAtCaret(textField, '', ':-(');}
	function controlsSetPissed(textField) {insertAtCaret(textField, '', ':-/');}
	function controlsSetBeer(textField) {insertAtCaret(textField, '', '(B)');}



/**
 * Insert string at the current caret position.
 *
 * @param {object} textField	The subject of the function.
 * @param {string} beforeStr	This string will be inserted before the caret.
 * @param {string} afterStr	This string will be inserted after the caret. Its default is ''.
 * @param {boolean} replace	If this flag is set to true, the inserted string
 *                         	replace the formerly selected text by the caret.
 *                         	Its default is false.
 * @param {boolean} select	If this flag is set to true, the inserted string (and the
 *                        	formerly selected text if replace was false) is selected.
 *                         	Its default is true.
 */
function insertAtCaret(textField, before, after, replace, select) {
	if (arguments.length < 3 || !after) after = '';
	if (arguments.length < 4 || !replace) replace = false;
	if (arguments.length < 5 || select) select = true;

	if (typeof textField.selectionStart != 'undefined') {
		var startPos = textField.selectionStart;
		var endPos = textField.selectionEnd;
		textField.value = textField.value.substr(0, startPos) + before
						+ (replace ? "" : textField.value.substring(startPos, endPos))
						+ after + textField.value.substr(endPos);
		if (select) {
			textField.setSelectionRange(startPos,
				endPos + before.length + after.length - (replace ? endPos-startPos : 0));
		} else {
			startPos = startPos + before.length + after.length;
			textField.setSelectionRange(startPos , startPos);
		}
	} else if (textField.createTextRange) {
		textField.focus();
		var pos = getCaret(textField);

		var range = document.selection.createRange();
		// Adding the before/after text to the textRange
		range.text = before+(replace ? "" : range.text)+after;

		// Selecting the needed text
		if (select) {
			pos.selectionLength = replace ? before.length + after.length :
				pos.selectionLength + before.length + after.length;
		} else {
			pos.position += before.length + after.length;
			pos.selectionLength = 0;
		}
		setCaret(textField, pos);
	} else {
		var position = textField.value.length+before.length;
		textField.value += (before + after);
		setCursorPosition(textField, position);
	}
}

/**
 * Get the caret position info of the given textfield
 *
 * @param {object} textField	The subject of the function.
 * @param {boolean} MSIEReturnNotLogicalPosition	This parameter is used for inner purpose.
 *
 * @return {object}	Returns a simple JavaScript object with position and selectionLength properties
 */
function getCaret(textField, MSIEReturnNotLogicalPosition)
{
	if (arguments.length < 2) MSIEReturnNotLogicalPosition = false;

	if (typeof textField.selectionStart != "undefined") {
		textField.focus();
		return {
			position: textField.selectionStart,
			selectionLength: textField.selectionEnd-textField.selectionStart
		};
	// Handling this issue in case of Internet Explorer need a little hack.
	// The problem is, that IE handle the concept of new line different
	// from text field value and textRange "character" unit point of view.
	// In the value the \r,\n charcters exist separately, but when use
	// the textRange.move("charcter", 1) new line is only one step.
	// That's why we need a little correction.
	} else if (textField.createTextRange) {
		var newLineNumAfterCursor = 0;
		match = textField.value.match(/\n/g);
		if (match) {
			newLineNumAfterCursor = match.length;
		}

		textField.focus();
		var position = textField.value.length;
		var selectionLength = document.selection.createRange().text.length;
		var cursor = document.selection.createRange().duplicate();

		while (cursor.parentElement() == textField && cursor.move('character', 1)) {
			if (textField.value.charAt(position - 1) == CONST_NL) {
				position -= 1;
				newLineNumAfterCursor--;
			}
			position--;
		}

		if (MSIEReturnNotLogicalPosition) {
			return {
				position: position + 1,
				selectionLength: selectionLength
			};
		} else {
			return {
				position: position + 1 - (newLineNumAfterCursor),
				selectionLength: selectionLength
			};
		}
	}
}

/**
 * Set the caret in the given textfield
 *
 * @param {object} textField	The subject of the function.
 * @param {object} pos	This parameter could be a number or a simple JavaScript
 *                    	object with position and selectionLength properties.
 *                    	If number was given the function creates a position
 *                    	object, where the position property is the given number
 *                    	and the selectionLength is 0. If the parameter is an
 *                    	object and has no position property, then the function
 *                    	set it to the current caret position. The selectionLength
 *                    	property could be negative.
 * @param {number} scrollTop	If this parameter is peresent, the function
 *                          	try to set the textField's scrollTop property.
 */
function setCaret(textField, pos, scrollTop)
{
	// If the function was called with a number only
	if (typeof pos == "number") {
		pos = {position: pos, selectionLength: 0}
	}
	// If the function was called with an object only with a selectionLength property
	if (typeof pos.position == "undefined") {
		pos.position = getCaret(textField).position;
	}
	// If negative selectionLength was given
	if (pos.selectionLength < 0) {
		pos.position += pos.selectionLength;
		pos.selectionLength = -pos.selectionLength;
	}

	if (typeof textField.selectionStart != 'undefined') {
		textField.focus();
		textField.setSelectionRange(pos.position, pos.position+pos.selectionLength);
	} else if (textField.createTextRange) {
		var textRange = textField.createTextRange();
		textRange.moveStart("character", pos.position);
		textRange.collapse();
		textRange.moveEnd("character", pos.selectionLength);
		textRange.select();
	}
	if (typeof scrollTop != "undefined" && typeof textField.scrollTop != "undefined") {
		textField.scrollTop = scrollTop;
	}
}

