// ncurses for the browser
// 
// Development build
// Extremely incomplete


var bcurses = new function () {

	var m, p, e, nwaits, target, buffer, screen, tymout;
	m = this;


	// Private class - Screen
	function Screen(w, h)
	{
		this.w		= w;
		this.h		= h;
		this.p		= {r:0, c:0};

		this.data	= new Array(w*h);
		this.flags	= 0;

		this.clear();
	};
	p = Screen.prototype;

	// Screen constants
	p.CLEAROK = 1;

	// Screen methods
	p.clear = function () {
		this.p = {r:0, c:0};
		for (var i = this.data.length-1; i >= 0; i--) this.data[i] = ' ';
	};

	p.clrtoeol = function () {
		var r=this.p.r, c=this.p.c;
		while (c < this.w) this.data[r*this.w+c++] = ' ';
	};

	p.clrtobot = function () {
		var i, stop=this.p.r*this.w + this.p.c;
		for (i = this.data.length-1; i >= stop; i--) this.data[i] = ' ';
	};

	p.printw = function (s) {
		var i, r, c;
		for (i=0, r=this.p.r, c=this.p.c; i < s.length; i++)
		{
			if (s.charAt(i) == '\n')
			{
				r += 1; c = 0;
			}
			else if (s.charAt(i) == '\b')
			{
				if (c) c--;
			}
			else
			{
				this.data[r*this.w+c] = s.charAt(i); c += 1;
				if (c >= this.w)
				{
					r += 1; c = 0;
				}
			}
		}
		this.p.r = r;
		this.p.c = c;
	};

	p.to_markup = function () {
		// ToDo
		// Need to render cursor
		// Need to handle effects
		var i, a;
		for (i = 0, a = []; i < this.data.length; i += this.w)
			a.push(this.data.slice(i,i+this.w).join(''));
		return a.join('\n');
	};


	// Private State
	nwaits = 0;
	target = undefined;
	buffer = undefined;
	screen = undefined;
	tymout = undefined;


	// Private Functions
	function HandleKeyboard(ev)
	{
		buffer.push(ev.key().string);
		ev.stop();
	};


	// Constants
	m.A_REVERSE		= 0;
	m.A_NORMAL		= 0;
	m.ERR			= 0;


	// Functions
	m.initscr = function () {
		// Initialize the library
		target = document.getElementById('screen');

		buffer = [];
		screen = new Screen(target.cols, target.rows);
		tymout = -1;

		disconnectAll(document, 'onkeydown');
		connect(document, 'onkeydown', HandleKeyboard);

		// ToDo:  IE6 doesn't support blur()? (for TEXTAREAs?)
		// disconnectAll(target, 'onfocus');
		// connect(target, 'onfocus', target, "blur");
	};

	m.flushinp = function () {
		// Discard typeahead
		buffer = [];
	};

	m.clear = function () {
		screen.clear();
		screen.flags != screen.CLEAROK;
	};

	m.clrtoeol = function () {
		screen.clrtoeol();
	};

	m.clrtobot = function () {
		screen.clrtobot();
	};

	m.printw = function (s) {
		screen.printw(s);
	};

	m.attrset = function (attr) {
		// ToDo
	};

	m.curs_set = function (flag) {
		// ToDo
	};

	m.refresh = function () {
		target.value = screen.to_markup();
	};

	m.getch = function (c) {
		var timeout = undefined;
		if (tymout >= 0)
		{
			timeout = new Date();
			timeout.setMilliseconds(timeout.getMilliseconds() + tymout);
		}

		if (nwaits)
			alert('Uh-Oh');
		nwaits++;

		function test () {
			if (buffer.length)
			{
				nwaits--;
				c(buffer.shift());
			}
			else if (timeout && (new Date() >= timeout))
			{
				nwaits--;
				c(m.ERR);
			}
			else
				setTimeout(test, 50);
		}
		test();
	};

	m.move = function (r, c) {
		screen.p.r = r;
		screen.p.c = c;
	};

	m.timeout = function (t) {
		tymout = t;
	};

	m.napms = function (ms, c) {
		if (nwaits)
			alert('Uh-Oh');
		nwaits++;
		setTimeout(function () { nwaits--; c(); }, ms);
	};


	// Export Globals
	for (e in this) window[e] = this[e];
}();
