var conn;

var CS_NOT_CONNECTED=0;
var CS_CONNECTED=1;
var CS_CONNECTION_FAILED=2;
var CS_CONNECTION_LOST=3;

var connection_state=CS_NOT_CONNECTED;

var recipient='dan@mauveinternet.co.uk';
var recipient_nick=false;

var httpbase='chat/';
//var httpbase='/';

function generateRandomID(dig)
{
	if (!dig)
		dig=8;
	var id='';
	for (var i=0; i < dig; i++)
		id=id+Math.floor(Math.random()*10);
	return id;
}

var resource_id=generateRandomID(2);

function filterOutgoingMessage(msg)
{
	if (!msg.match(/(\.|!|\?)$/))
		msg=msg+'.';
	msg=msg.charAt(0).toUpperCase()+msg.substring(1);
	return msg;
}

function initChat()
{
	conn=new JSJaCHttpBindingConnection({httpbase: httpbase+'httpb/', timerval: 100});
	//conn=new JSJaCHttpPollingConnection({httpbase: httpbase+'httpp/', timerval: 2000});

	conn.registerHandler('onconnect', chatConnect);
	conn.registerHandler('onerror', chatError);
	
	conn.registerHandler('message', chatMessage);
	conn.registerHandler('presence', chatPresence);

	messagewindow.create();

	var stored_talkid=getCookie('talkid');
	var stored_pass=getCookie('talkpass');
	if (stored_talkid && stored_pass)
	{
		conn.connect({
			domain: 'mauveinternet.co.uk',
			username: 'guest.'+stored_talkid,
			resource: resource_id,
			pass: stored_pass,
			authtype: 'nonsasl'
		});
	}
	else
	{
		var talkid=generateRandomID();
		var pass=generateRandomID(12);
		
		setCookie('talkid', talkid, 2020, 0, 1);
		setCookie('talkpass', pass, 2020, 0, 1);
	
		conn.connect({
			domain: 'mauveinternet.co.uk',
			username: 'guest.'+talkid,
			resource: resource_id,
			pass: pass,
			register: true,
			authtype: 'nonsasl'
		});
	}

	addEvent(window, 'unload', chatDisconnect, false);

}

function patchLinks()
{
	var as=document.getElementsByTagName('a');

	for (var i=0; i < as.length; i++)
	{
		registerLinkTravelEvent(as[i]);
	}
}

function registerLinkTravelEvent(a)
{
	addEvent(a, 'click', function (e) {
		var m=new JSJaCMessage();
		m.setType('normal');
		m.setBody('-> '+a.href);
		m.setTo(recipient);
		conn.send(m);

		if (e && e.preventDefault)
			e.preventDefault();
		else
			window.event.returnValue=false;
		setTimeout(function () {
			location.href=a.href;
		}, 50);
	}, false);
}

function getNameForUser(user)
{
	var res=user.match(/([^\/]+)@.*/);
	if (res)
		user=res[1].charAt(0).toUpperCase()+res[1].substr(1).toLowerCase();
	
	return user;
}

addEvent(window, 'load', initChat, false);
//registerOnLoadFunction(initChat);

function MessageWindow()
{
	this.create=function()
	{
		this.windowpane=createHTMLElement('div');
		this.windowpane.id='chatbox';
	
		var minimize=createHTMLElement('img');
		minimize.id='minimize';
		minimize.src='chat/assets/minimize.png';

		addEvent(minimize, 'click', function() {
			messagewindow.setVisible(false);
			setAway();
		}, false);

		this.pane=createHTMLElement('div');
		this.pane.id='messages';

		this.windowpane.style.display='none';	//set visibility (but don't persist this)
		document.body.appendChild(this.windowpane);
		this.windowpane.appendChild(minimize);
		this.windowpane.appendChild(this.pane);

		var line=createHTMLElement('input');
		line.id='line';
		this.windowpane.appendChild(line);

		this.windowpane.getDimensions=function ()
		{
			var dims=new Object;
			dims.w=(this.offsetWidth)?this.offsetWidth:400;
			dims.h=(this.offsetHeight)?this.offsetHeight:300;
			return dims;
		}

		addEvent(line, 'focus', setFreeForChat, false);
		addEvent(line, 'blur', setOnline, false);
		addEvent(line, 'keydown', function (e) {
			if (e.keyCode == 13)
			{
				var msg=filterOutgoingMessage(line.value);
				line.value='';
				sendChatMessage(msg);
				messagewindow.addOutgoingMessage(msg);
			}
		}, false);

		addEvent(window, 'blur', function (e) {
			setExtendedAway();
			if (window.event)
				window.event.cancelBubble=true;
			else
				e.stopPropagation();
		}, false);

		setupChatboxPositioning();
	}

	this.getMessagePane=function ()
	{
		if (!this.pane)
			this.pane=document.getElementById('messages');

		return this.pane;
	}

	this.getWindowPane=function ()
	{
		if (!this.windowpane)
			this.windowpane=document.getElementById('chatbox');

		return this.windowpane;
	}

	this.isVisible=function ()
	{
		return this.getWindowPane().style.display != 'none';
	}

	this.setVisible=function (vis)
	{
		if (vis)
		{
			if (!this.isVisible())
			{
				this.getWindowPane().style.display='block';
				var line=document.getElementById('line');
				line.focus();
				setCookie('bvis', 'v');
			}
		}
		else
		{
			if (this.isVisible())
			{
				this.getWindowPane().style.display='none';
				setCookie('bvis', 'h');
			}
		}
	}

	this.restoreVisibility=function()
	{
		if (getCookie('bvis') == 'v')
			this.setVisible(true);
		else
			this.setVisible(false);
	}

	this._scrollpane=function()
	{
		var m=this.getMessagePane();
		
		//attempt to scroll to the bottom
		//TODO: don't do this if we're not already at the bottom
		m.scrollTop=m.scrollHeight-m.offsetHeight;
	}

	this._message=function(text, className)
	{
		var p=document.createElement('p');
		if (className)
			p.className=className;
		p.appendChild(document.createTextNode(text));
		var m=this.getMessagePane();
		m.appendChild(p);

		this._scrollpane();
		this.lastdiv=null;
	}

	this._chatmessage=function(text, user)
	{
		if (this.lastdiv && user == this.lastuser)
		{
			var div=this.lastdiv;
		}
		else
		{
			var div=document.createElement('div');

			this.lastdiv=div;
			this.lastuser=user;

			div.className='message';
			var name=document.createElement('strong');
			if (!user)
			{
				div.className='message you';
				user='You';
			}
			else
			{
				user=getNameForUser(user);
			}
			name.appendChild(document.createTextNode(user));
			div.appendChild(name);
		}

		var p=document.createElement('p');
		p.appendChild(document.createTextNode(text));
		div.appendChild(p);
		var m=this.getMessagePane();
		m.appendChild(div);

		this.setVisible(true);
		this._scrollpane();
	}

	this.addStatusMessage=function(text)
	{
		this._message(text, 'status');
	}

	this.addIncomingMessage=function(user, text)
	{
		this._chatmessage(text, user);
	}

	this.addOutgoingMessage=function(text)
	{
		this._chatmessage(text);
	}

	this.addError=function(text)
	{
		this._message('Error: '+text, 'error');
	}
}

var messagewindow=new MessageWindow('messages');

function message(msg, className)
{
	messagewindow._message(msg, className);
}

function chatError(e)
{
	switch (e.firstChild.nodeName)
	{
		case 'service-unavailable':
		case 'remote-connection-failed':
			messagewindow.addError('The connection to the messaging server has failed.');
			break;
			

		default:
			messagewindow.addError(e.firstChild.nodeName);
			break;
	}	
}

function chatConnect()
{
	connection_state=CS_CONNECTED;
	//message('Connected, waiting for response.', 'status');
	
	setOnline();
	
	var m=new JSJaCMessage();
	m.setType('normal');
	m.setBody('Client connected via '+location.href);
	m.setTo(recipient);
	conn.send(m);

	messagewindow.restoreVisibility();
	patchLinks();
	
	//subscribePresence(recipient);
	//	requestVCard();
}

function subscribePresence(user)
{
	var m=new JSJaCPresence();
	m.setType('subscribe');
	m.setTo(user);
	conn.send(m);
	
	var m=new JSJaCPresence();
	m.setType('subscribed');
	m.setTo(user);
	conn.send(m);
}

function setFreeForChat()
{
	if (connection_state != CS_CONNECTED) return;
	
	var m=new JSJaCPresence();
	m.setShow('chat');
	conn.send(m);
}

function setAway()
{
	if (connection_state != CS_CONNECTED) return;
	
	var m=new JSJaCPresence();
	m.setShow('away');
	conn.send(m);
}

function setExtendedAway()
{
	if (connection_state != CS_CONNECTED) return;

	var m=new JSJaCPresence();
	m.setShow('xa');
	conn.send(m);
}

function setOnline()
{
	if (connection_state != CS_CONNECTED) return;
	
	var m=new JSJaCPresence();
	conn.send(m);
}

function sendChatMessage(body)
{
	if (connection_state != CS_CONNECTED) return;

	var m=new JSJaCMessage();
	m.setType('chat');
	m.setBody(body);
	m.setTo(recipient);
//	m.setFrom(conn.jid);
	conn.send(m);
}

function updateRecipientStatus(status)
{
	var rc=document.getElementById('recipientstatus');
	if (!rc)
		return;
	while (rc.lastChild)
		rc.removeChild(rc.lastChild);
	
	rc.appendChild(document.createTextNode(status));
}

function chatMessage(packet)
{
	var text=packet.getSubject()+' '+packet.getBody();
	if (text != ' ')
		messagewindow.addIncomingMessage(packet.getFrom(), text);
}

function chatPresence(packet)
{
	switch (packet.getType())
	{
		case null:
			var from=packet.getFrom();
			if (from == conn.jid || from == conn.fulljid)
				return;
			from=getNameForUser(from);
			switch(packet.getShow())
			{
				case '':
					message(from+' is online.', 'presence');
					updateRecipientStatus('Online');
					break;

				case 'chat':
					message(from+' is free for chat.', 'presence');
					updateRecipientStatus('Free for Chat');
					break;
				
				case 'away':
					message(from+' is momentarily unavailable.', 'presence');
					updateRecipientStatus('Away');
					break;
					
				case 'xa':
					message(from+' is unavailable.', 'presence');
					updateRecipientStatus('Unavailable');
					break;

				default:
					message(packet.getFrom()+': unknown presence.', 'error');
			}
			break;


		case 'unavailable':
			message(packet.getFrom()+' is offline.',  'presence');
			updateRecipientStatus('Offline');
			break;
	
		default:
		//	message("Presence from "+packet.getFrom());
		//	message(" - type "+packet.getType());
		//	message(" - show "+packet.getShow());
		//	message(" - status "+packet.getStatus());

			if (packet.getType() == 'subscribe')
			{
				if (connection_state != CS_CONNECTED) return;
				var m=new JSJaCPresence();
				m.setType('subscribed');
				m.setTo(packet.getFrom());
				//m.setFrom(conn.jid);
				conn.send(m);
			}
			break;
	}
}

function chatDisconnect()
{
	var m=new JSJaCPresence();
	m.setType('unavailable');
	conn.send(m);
	conn.disconnect();
}

function requestVCard()
{
	var m=new JSJaCIQ();
	m.setType('get');
	m.setTo(recipient);
	m.setFrom(conn.jid);
	
	var doc=m.getDoc();
	var vc=doc.createElementNS('vcard-temp', 'vCard');
	doc.documentElement.appendChild(vc);

	conn.send(m, vCardReceived);
}

function vCardReceived(packet)
{
	var nicknames=packet.getQuery().getElementsByTagName('NICKNAME');

	if (nicknames.length > 0)
		recipient_nick=nicknames[0].firstChild.nodeValue;

	message(recipient_nick+": Hello, can I help you?", 'message');
		
}
