var Parser = new function () {
	this.hLut = new Array(256);
	this.cLut = new Array(256);

	this.rvHex0 = new Array(8);
	this.rvTxt0 = new Array(8);
	this.rvHex1 = new Array(8);
	this.rvTxt1 = new Array(8);


	var lut = String('0123456789ABCDEF').split('');
	for (var h = 0; h < 16; h++)
	{
		for (var l = 0; l < 16; l++)
		{
			this.hLut[h*16+l] = lut[h]+lut[l];
		}
	}
	this.hLut[undefined] = '\u00a0\u00a0';

	for (var i = 0; i < 256; i++)
	{
		if ((i < 32) || (i > 126))
		{
			this.cLut[i] = '.';
		}
		else if (i == 32)
		{
			this.cLut[i] = '\u00a0';
		}
		else
		{
			this.cLut[i] = String.fromCharCode(i);
		}
	}
	this.cLut[undefined] = '\u00a0';


	this.DwordToHex = function (n) {
		var rv = [];
		while (n)
		{
			rv.unshift(this.hLut[n&0xff]);
			n >>= 8;
		}
		while (rv.length < 4)
		{
			rv.unshift('00');
		}
		return rv.join('');
	};

	this.PrintSegment = function (a, i, h, t) {
		var o, c;
		for (o = 0; o < 8; o++)
		{
			c = a[i+o];
			h[o] = this.hLut[c];
			t[o] = this.cLut[c];
		}
	};

	this.PrintRowDetail = function (a, i) {
		this.PrintSegment(a, i, this.rvHex0, this.rvTxt0);
		this.PrintSegment(a, i+8, this.rvHex1, this.rvTxt1);

		return	this.DwordToHex(i) +
			'\u00a0\u00a0' +
			this.rvHex0.join(' ') + '\u00a0--\u00a0' + this.rvHex1.join(' ') +
			'\u00a0\u00a0' +
			this.rvTxt0.join('') + this.rvTxt1.join('');
	};

	this.AppendRowDetail = function (d, a, i) {
		var p = document.createElement('P');
		var span = document.createElement('SPAN');
		span.className = 'row'+((i>>4)&0x01);
		span.appendChild(document.createTextNode(this.PrintRowDetail(a, i)));
		p.appendChild(span);
		d.appendChild(p);
	};

	this.PrintRowSimple = function (a, i) {
		this.PrintSegment(a, i, this.rvHex0, this.rvTxt0);
		this.PrintSegment(a, i+8, this.rvHex1, this.rvTxt1);

		return	this.rvHex0.join(' ') + '\u00a0--\u00a0' + this.rvHex1.join(' ') +
			'\u00a0\u00a0' +
			this.rvTxt0.join('') + this.rvTxt1.join('');
	};

	this.AppendRowSimple = function (d, a, i) {
		var p = document.createElement('P');
		p.appendChild(document.createTextNode(this.PrintRowSimple(a, i)));
		d.appendChild(p);
	};

	this.Display = function (id, data, bShowDetail) {
		var d = document.getElementById(id);
		if (d.firstChild)
		{
			d.removeChild(d.firstChild);
		}

		var div = document.createElement('DIV');
		var fxn = bShowDetail?this.AppendRowDetail:this.AppendRowSimple;
		for (var i = 0; i < data.length; i += 16)
		{
			fxn.apply(this, [div, data, i]);
		}
		d.appendChild(div);
	}
}();


function DisplayDiagnostic(name, value)
{
	var s = document.getElementById(name);
	if (s.firstChild)
	{
		s.removeChild(s.firstChild);
	}
	s.appendChild(document.createTextNode(value));
}

function DisplayDiagnostics(diagnostics)
{
	document.getElementById('diagnostic').style.display = "block";

	DisplayDiagnostic('diag_transit', diagnostics.t1-diagnostics.t0);
	DisplayDiagnostic('diag_decode', diagnostics.t2-diagnostics.t1);
	DisplayDiagnostic('diag_display', diagnostics.t3-diagnostics.t2);
	DisplayDiagnostic('diag_total', diagnostics.t3-diagnostics.t0);
}

function DisplayNotification(msg)
{
	// Delete old output
	var d = document.getElementById('display');
	if (d.firstChild)
	{
		d.removeChild(d.firstChild);
	}

	// Post message
	var p = document.createElement('P');
	p.appendChild(document.createTextNode(msg));
	d.appendChild(p);
}

function Start()
{
	// Record start time
	top.ProcessAjaxResponse.diagnostics = {t0:new Date()};

	// Hide diagnostics
	document.getElementById('diagnostic').style.display = "none";

	// Post message
	DisplayNotification('Loading data - please wait.');
}

function ProcessAjaxResponse()
{
	// Measure response time
	var diagnostics = top.ProcessAjaxResponse.diagnostics;
	diagnostics.t1 = new Date();

	// Unpack data (w/ timing)
	var contentNode = window.frames['ajax'].document.getElementById('payload');
	var data = Base64.Decode(contentNode.innerHTML);
	diagnostics.t2 = new Date();

	// Display data (w/ timing)
	Parser.Display('display', data, true);
	diagnostics.t3 = new Date();

	// Display diagnostics
	DisplayDiagnostics(diagnostics);
}
