function makeXMLHttpRequest ()
{
	var factories = [
		function () { return new XMLHttpRequest(); },
		function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
		function () { return new ActiveXObject("Microsoft.XMLHTTP"); }
	];
	
	for (var i = 0; i < factories.length; i++)
	{
		try
		{
			return factories[i]();
		}
		catch (ex) { }
	}
	
	throw new Error("Unable to create XMLHttpRequest");
}

function doSubmit ()
{
	var input = document.getElementById('entry');
	var entry = input.value;
	
	// Save history as if we were at the bottom
	historyPointer = -1;
	saveHistory();
	
	input.value = '';
	
	addLine('input', entry);
	
	var req = makeXMLHttpRequest();
	req.onreadystatechange = function ()
	{
		if (req.readyState == 4)
		{
			addLine('output', req.responseText);
		}
	}
	
	var sid = document.getElementById('sid');
	var sidname = sid.attributes.getNamedItem("name").value;
		
	var params =
		"input=" + encodeURIComponent(entry) +
		"&" + sidname + "=" + encodeURIComponent(sid.value);
	
	req.open("POST", "webquery.php", true);
	req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
	req.setRequestHeader("Content-Length", params.length);
	req.send(params);
	
	return false;
}

function addLine (type, text)
{
	var lines = document.getElementById('lines');
	
	if (type == 'input')
	{
		text = '> ' + text;
	}
	
	var line = document.createElement('code');
	line.className = type;
	line.appendChild(document.createTextNode(text));
	
	var bottom = window.scrollMaxY ? window.scrollMaxY : Math.pow(2, 16);
	
	lines.appendChild(line);
	window.scrollTo(0, bottom);
	document.getElementById('entry').focus();
			
}

function catchMouseDown ()
{
	mouseTimer = new Date();
}


function catchMouseUp ()
{
	var now = new Date();
	
	// If mouse is down too long, assume we are copypasting and don't focus
	if (mouseTimer == null ||
		now.getTime() - mouseTimer.getTime() < mouseTimeout)
	{
		document.getElementById('entry').focus();
		var bottom = window.scrollMaxY ? window.scrollMaxY : Math.pow(2, 16);
		window.scrollTo(0, bottom);
	}
	
	mouseTimer = null;
}

function navHistory (e)
{
	// Handle compatibility between browsers
	var evt = window.event ? event : e;
	var code = evt.keyCode ? evt.keyCode : evt.charCode;
	
	switch (code)
	{
		case 38: // Up arrow
			upHistory();
			break;
			
		case 40: // Down arrow
			downHistory();
			break;
			
		default:
			return true;
	}
	
	return false;
}

function saveHistory ()
{
	var input = document.getElementById('entry').value;
	input = input.replace(/^\s+|\s+$/, '');
	
	// Don't save just whitespace
	if (input.length == 0)
	{
		return false;
	}
	else if (inputHistory.length > 0)
	{
		// Don't save if we're scrolling history at the moment
		if (historyPointer > -1)
		{
			if (input == inputHistory[historyPointer])
			{
				return false;
			}
		}
		// Don't save, if we're at the bottom and trying to save the same thing
		else
		{
			if (input == inputHistory[0])
			{
				return false;
			}
		}
	}	
	
	// Save input into inpur history
	inputHistory.unshift(input);
	
	return true;
}

function upHistory ()
{
	// if we saved, start over (skipping the first)
	if (saveHistory())
	{
		historyPointer = 0;
	}
	
	// Can't do history if there is none
	if (inputHistory.length < 1)
	{
		return false;
	}
	
	// if we reached last entry, do nothing
	if (historyPointer >= inputHistory.length - 1)
	{
		return false;
	}
	
	// Get from history
	var entry = document.getElementById('entry');
	entry.value = inputHistory[++historyPointer];
	
	return true;
}

function downHistory ()
{
	// If we saved, give an empty input
	if (saveHistory())
	{
		historyPointer = -1;
	}
	
	historyPointer--;
	
	var value = '';
	
	// if we're at the bottom, give an empty input
	if (historyPointer < 0)
	{
		historyPointer = -1;
	}
	// If we're scrolling history, show the appropriate history line
	else
	{
		value = inputHistory[historyPointer];
	}
	
	var entry = document.getElementById('entry');
	entry.value = value;
	
	return true;
}
