
var sNoSnippets = "";
var sWarning = "";
var sSnippetKey ="";
var rgSnippet = [];
var elemSnippetHelperTarget;
var elemSnippetWarningTarget;
var bSnippetHelperOn = false;
var sSnippetHelperSToReplace;

// Replaces n characters before selection with the text of the snippet
// and highlights the first area of the form [[...]]
// elemTarget - The elemTarget textarea	
// sName - The string to replace
// s - The text of the snippet
function replaceWithSnippet(elemTarget, sName, s) {
	s = replacePlaceHolders(s);
	var n = sName.length;
	var nStartBrackets, nEndBrackets;
	//IE support
	safeFocus(elemTarget);
	if (document.selection && !window.opera) 
	{
		var sel = document.selection.createRange();
		sel.collapse();
		sel.moveStart("character", -n);
		sel.text=s;
		nStartBrackets = s.search(/\[\[/);
		nEndBrackets = s.search(/\]\]/);
		if (nStartBrackets != -1 && nEndBrackets != -1)
		{
			sel.moveStart("character", -s.length + nStartBrackets);
			sel.moveEnd("character", -s.length + nEndBrackets + 2);
		}
		sel.select();
		sel.scrollIntoView();
	}
	//Mozilla/Netscape/Firefox support
	else if (elemTarget.selectionStart || elemTarget.selectionStart == '0') 
	{
		var nEndPos = Math.max(0, elemTarget.selectionStart);
		var nStartPos = Math.max(0, nEndPos - n);
		
		var sPreSnippet = elemTarget.value.substring(0, nStartPos);
		var sPostSnippet = elemTarget.value.substring(nEndPos, elemTarget.value.length);
		
		var pxScrollHeightPreSnippet, pxScrollHeightSnippet, pxScrollToPreSelectionBlock;
		
		nStartBrackets = s.search(/\[\[/);
		nEndBrackets = s.search(/\]\]/);
		
		// Get the scroll height of all text before the snippet insertion point
		elemTarget.value = sPreSnippet;
		pxScrollHeightPreSnippet = elemTarget.scrollHeight;
		
		if (nStartBrackets != -1 && nEndBrackets != -1)
		{
			// Get the scroll height of all text before the first snippet bracket selection point
			elemTarget.value = elemTarget.value + s.substring(0, nStartBrackets);
			pxScrollToPreSelectionBlock = elemTarget.scrollHeight - elemTarget.offsetHeight;
		}
		
		// Get the scroll height of the actual snippet
		elemTarget.value = sPreSnippet + s;
		pxScrollHeightSnippet = elemTarget.scrollHeight - pxScrollHeightPreSnippet;
		
		elemTarget.value = elemTarget.value + sPostSnippet;
		
		// Attempt to scroll the end of the snippet to the bottom of the textarea
		var pxScrollTo = pxScrollHeightPreSnippet + pxScrollHeightSnippet - elemTarget.offsetHeight;
		
		if (nStartBrackets != -1 && nEndBrackets != -1)
		{
			elemTarget.setSelectionRange(nStartPos + nStartBrackets,
			nStartPos + nEndBrackets + 2); 
			
			if (pxScrollToPreSelectionBlock < pxScrollTo)
			{
				// Don't scroll the first snippet bracket selection point out of view
				pxScrollTo = pxScrollToPreSelectionBlock;
			}
		}
		else
		{
			var nNewCursorPos = nStartPos + s.length;
			elemTarget.setSelectionRange(nNewCursorPos, nNewCursorPos);
			if (window.opera) redraw(elemTarget);
		}
		
		elemTarget.scrollTop = Math.max(0, pxScrollTo);
	}
	else
	{
		var txt = elemTarget.value;
		var nCursorPos = txt.lastIndexOf(sName + sSnippetKey);
		if (nCursorPos > -1)
		{
			nCursorPos = nCursorPos + n;
			elemTarget.value = "";
			elemTarget.blur();
			elemTarget.value = txt.substring(0, nCursorPos - n) + s + txt.substring(nCursorPos + 1);
			safeFocus(elemTarget);
		}
	}
}


// Looks at the cursor and searches to the last whitespace to find the text
// that the user is trying to snippet-replace
// elemTarget - The elemTarget textarea	
function getSnippetName(elemTarget)
{
	var sNameBuffer = '';
	//IE support
	if (document.selection && !window.opera) 
	{
		safeFocus(elemTarget);
		sel = document.selection.createRange();
		sel.collapse();
		sel.moveStart("word", -1);
		selSlashcheck = sel.duplicate();
		selSlashcheck.moveStart("character", -1);
		selSlashcheck.moveStart("word", -1);
		var nSlashSections = 1;
		while (	selSlashcheck.text != "" && 
			(selSlashcheck.text.lastIndexOf(sSnippetKey) != selSlashcheck.text.length-1) && 
			selSlashcheck.text.indexOf("/") != -1 && 
			selSlashcheck.text.indexOf("\n") < 0 &&
			selSlashcheck.text.indexOf(" ") < 0 &&
			selSlashcheck.text.split("/").length != nSlashSections)
		{
			sel = selSlashcheck.duplicate();
			nSlashSections = selSlashcheck.text.split("/").length;
			selSlashcheck.moveStart("character", -1);
			selSlashcheck.moveStart("word", -1);
		}
		sNameBuffer = sel.text;
		if (sNameBuffer.lastIndexOf(' ') > -1)
		{
			sNameBuffer = "";
		}
	}
	//Mozilla/Netscape/Firefox support
	else if (elemTarget.selectionStart || elemTarget.selectionStart == '0') 
	{
		var nNameEnd = Math.max(0, elemTarget.selectionStart);
		var nNameStart = Math.max(0, nNameEnd - 16); 
		sNameBuffer = elemTarget.value.substr(nNameStart, nNameEnd - nNameStart);
		var saNames = sNameBuffer.split(/\s/);
		sNameBuffer = saNames[saNames.length - 1];
	}
	return sNameBuffer;
}


function doSnippetAction(elemTarget, e, sSnippetName)
{
	if (rgSnippet.length == 0)
	{
		showSnippetWarning(elemTarget, sNoSnippets);
		return true;
	}
	else if (sSnippetName.length == 0)
	{
		sSnippetHelperSToReplace = "";
		return false;
	}
	else if (sSnippetName.charAt(sSnippetName.length - 1) == sSnippetKey)      
	{
		sSnippetHelperSToReplace = sSnippetName;

		if (document.selection || elemTarget.selectionStart || elemTarget.selectionStart == '0')
		{
			replaceWithSnippet(elemTarget, sSnippetKey, "");
			sSnippetHelperSToReplace = sSnippetHelperSToReplace.substring(0, sSnippetHelperSToReplace.length-1);
		}
		showSnippetHelper(elemTarget);
		return cancel(e);
	}
	else
	{
		var sLCSnippetName = sSnippetName.toLowerCase();
		for (i = 0; i < rgSnippet.length; i++)
		{ 
			if (sLCSnippetName == rgSnippet[i].name.toLowerCase())
			{
					replaceWithSnippet(elemTarget, sSnippetName, rgSnippet[i].text);
					return cancel(e);
			}
		}
		// Not a known snippet
		sSnippetHelperSToReplace = sSnippetName;
		var ixReplace = sWarning.indexOf("%1");
		showSnippetWarning(elemTarget, sWarning.substring(0,ixReplace) + sSnippetName + sWarning.substring(ixReplace+2));
		return true;
	}
}


function replaceFirstSnippetInstance(elemTarget)
{
	var sNameBuffer = "";
	var nCursorPos = elemTarget.value.lastIndexOf(sSnippetKey);
	sNameBuffer = elemTarget.value.substring(0, nCursorPos);
	var nNameStart = Math.max(0, Math.max(sNameBuffer.lastIndexOf(" "), sNameBuffer.lastIndexOf("\n")) + 1);
	var nNameEnd = nCursorPos;
	sNameBuffer = sNameBuffer.substr(nNameStart, nNameEnd - nNameStart);
	return doSnippetAction(elemTarget, null, sNameBuffer);
}


// Set this as the onkeypressed event for the textarea to use snippets
// elemTarget - The elemTarget textarea	
// e- The keypress event that triggered this handler	
function handleSnippetTargetKeypress(elemTarget, e)
{
	bUserTyped = true;
	hideSnippetWarning();
	var keyPressed = String.fromCharCode(getKeyCode(e));
	if (keyPressed == sSnippetKey)
	{ 
		// If we don't have a mechanism for getting the cursor position, set a timeout and do it the hard way
		if (!(document.selection || elemTarget.selectionStart || elemTarget.selectionStart == '0'))
		{
			setTimeout('replaceFirstSnippetInstance(' + elemTarget.id + ')', 100);
			return true;
		}
		else
		{
			var sSnippetName = getSnippetName(elemTarget);
			return doSnippetAction(elemTarget, e, sSnippetName);
		}
			
	}
}


function showSnippetWarning(elemTarget, sWarning)
{
	elemSnippetWarningTarget = elemTarget;
	var elemWarning = elById('idSnippetWarning'); 
	var pos = getAbsolutePosition(elemTarget);
	elemWarning.style.left = pos.x + elemTarget.offsetWidth - elemWarning.offsetWidth + "px";
	elemWarning.style.top = pos.y + "px";
	elemWarning.innerHTML = sWarning;
	elemWarning.style.visibility='visible';
	safeFocus(elemTarget);
	showSnippetClickMask();
}


function hideSnippetWarning()
{
	elById('idSnippetWarning').style.visibility='hidden';
	if (elemSnippetWarningTarget) safeFocus(elemSnippetWarningTarget);
	hideSnippetClickMask();
}


function showSnippetHelper(elemTarget)
{
	var elemHelper = elById('idSnippetHelper');
	var elemSnipText = elById('idSnippetText');
	var elemSelectbox = elById('idSnippetSelect');
	var elemOkButton = elById('idSnippetOKButton');

	elemSnippetHelperTarget = elemTarget;
	
	if (elemSelectbox.length != rgSnippet.length)
		populateSnippetSelect();

	if (!bSnippetHelperOn)
	{
		bSnippetHelperOn = true;
		if (clickmaskSnippet) clickmaskSnippet.style.display = "";
		// Shrink the elemTarget window	
		elemTarget.style.height = Math.round(elemTarget.offsetHeight / 2) + "px";

		// Size the helper and all of its components
		var nSelStart;
		var nSelEnd;
		if (!document.selection && elemTarget.selectionStart && elemTarget.selectionEnd)
		{
 			nSelStart = elemTarget.selectionStart;
 			nSelEnd = elemTarget.selectionEnd;
		}
		elemHelper.style.display='block';
		if (!document.selection && elemTarget.selectionStart && elemTarget.selectionEnd)
		{
 			elemTarget.selectionStart = nSelStart;
 			elemTarget.selectionEnd = nSelEnd;
		}
		elemHelper.style.width = elemTarget.offsetWidth + "px";
		var pos = getAbsolutePosition(elemTarget);
		elemHelper.style.left = pos.x + "px";
		elemHelper.style.top = pos.y + elemTarget.offsetHeight + "px";
		elemSnipText.style.height = elemSelectbox.offsetHeight - elemOkButton.offsetHeight - 10 + "px";
		elemSnipText.style.width = elemTarget.offsetWidth - elemSelectbox.offsetWidth - 15 + "px";
		showSnippetClickMask();
	}

	if (elemOkButton.focus) safeFocus(elemOkButton); // Get the entire helper in view
	if (elemSelectbox.focus) safeFocus(elemSelectbox); // Give the focus to the select box

	refreshSnippetHelper();
}


function hideSnippetHelper()
{
	var elemHelper = elById('idSnippetHelper');
	if (bSnippetHelperOn)
	{
		bSnippetHelperOn = false;
		elemHelper.style.display='none';
		elemSnippetHelperTarget.style.height = "";
		redraw(elemSnippetHelperTarget);
		safeFocus(elemSnippetHelperTarget);
		hideSnippetClickMask();
	}
}


function refreshSnippetHelper()
{
	var ixSnippet = elById('idSnippetSelect').selectedIndex;
	var reLT = new RegExp('<', 'gi');
	var reGT = new RegExp('>', 'gi');
	if (ixSnippet > -1)
	{
		var sTipText = rgSnippet[ixSnippet].text;
		sTipText = encodeLTGT(sTipText);
		var s = "<span class=snippetText>" + sTipText + "</span>";
		var sComment = encodeLTGT(rgSnippet[ixSnippet].comment);
		if (sComment.length > 0)
			s = "<span class=snippetComment>" + sComment + "</span><hr>" + s;
		elById('idSnippetText').innerHTML = s;
	}
}


function populateSnippetSelect()
{
	var elemSelectbox = elById('idSnippetSelect');

	while (elemSelectbox.length > 0) elemSelectbox.remove(0);

	var newopt;

	for (i = 0; i < rgSnippet.length; i++)
	{
		optNew = new Option(rgSnippet[i].name, rgSnippet[i].name, i==0, i==0);
		if (document.all)
			elemSelectbox.add(optNew); // IE
		else
			elemSelectbox.add(optNew, null); // Mozilla/Netscape/Firefox
		if (i == 0) optNew.selected = true;
	}

}


function handleSnippetHelperOK(e)
{
	hideSnippetHelper();
	var ixSnippet = elById('idSnippetSelect').selectedIndex;
	if (ixSnippet > -1)
		replaceWithSnippet(elemSnippetHelperTarget, sSnippetHelperSToReplace, rgSnippet[ixSnippet].text);
	return cancel(e);
}


function handleSnippetHelperCancel(e)
{
	hideSnippetHelper();
	return cancel(e);
}


function handleSnippetSelectKeypress(e)
{
	if (getKeyCode(e) == 13)
		return handleSnippetHelperOK(e);
	else if (getKeyCode(e) == 27)
		return handleSnippetHelperCancel(e);
}

function showSnippetClickMask()
{
	if (typeof clickmaskSnippet == "undefined" || !clickmaskSnippet) return;
	clickmaskSnippet.style.top = "0px";
	clickmaskSnippet.style.left = "0px";
	clickmaskSnippet.style.width = documentWidth() + 'px';
	clickmaskSnippet.style.height = documentHeight() + 'px';
	clickmaskSnippet.style.display = "";
}

function hideSnippetClickMask()
{
	if (typeof clickmaskSnippet == "undefined" || !clickmaskSnippet) return;
	clickmaskSnippet.style.display = "none";
}

// END SNIPPET STUFF
