/**
* chat.js
*
* @package Chat
* @version 0.2
* @copyright (c) 2008 phpBB3.PL Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

chat = {
	lang: null, // To be set by the template.
	XHR: null,

	construct: function()
	{
		chat.template.construct();
		chat.updater.construct();
		chat.postingEngine.construct();
		chat.actionEngine.construct();
	},

	// Do NOT try to execute it - it should be copied to XHR objects.
	onXHRReadyStateChange: function()
	{
		// this == an XHR... Not in Firefox 2.
		if (chat.XHR.readyState == 4)
		{
			if (chat.XHR.responseXML)
			{
				var response = chat.XHR.responseXML.documentElement;
				response.type = response.getAttribute('type');
				if (!response.textContent)
				{
					response.textContent = response.innerText;
				}

				chat.XHR.handleResponse(response);
			}
			else
			{
				chat.XHR.handleResponse();
			}
		}
	},

	template: null, // To be set by the template.

	updater: {
		updateEveryXSeconds: 5,

		running: false,
		XHR: null,

		action: null,
		lastMessageID: null,

		construct: function()
		{
			if (!window.XMLHttpRequest)
			{
				return;
			}

			var XHR = new XMLHttpRequest();
			XHR.handleResponse = this.applyChanges;
			XHR.onreadystatechange = chat.onXHRReadyStateChange;
			chat.updater.XHR = XHR; // Store it somewhere

			window.setInterval(this.checkForChanges, this.updateEveryXSeconds * 1000);
		},

		checkForChanges: function()
		{
			if (chat.postingEngine.running || (chat.updater.running && chat.updater.XHR.readyState != 4))
			{
				// Running two XHR requests at one time is a bad idea.
				return;
			}

			chat.updater.running = true;

			var XHR = chat.XHR = chat.updater.XHR;
			XHR.onreadystatechange = chat.onXHRReadyStateChange; // Fixes a stupid Firefox bug.
			XHR.open('GET', chat.updater.action + '&messageID=' + chat.updater.lastMessageID, true);
			XHR.setRequestHeader('Accept', 'application/xml,application/x-oapi-response+xml;q=0.5');
			XHR.send(null); // Firefox needs it...
		},

		applyChanges: function(response)
		{
			chat.updater.running = false;

			if (!response)
			{
				return;
			}

			var responseChildren = response.getElementsByTagName('messages');

			for (var i = 0; i < responseChildren.length; i++)
			{
				var messages = responseChildren[i];

				if (!messages.getAttribute('id'))
				{
					// null error... No idea why it occurs, but it occurs.
					return;
				}

				if (!document.getElementById(messages.getAttribute('id')))
				{
					chat.template.addDate(messages.getAttribute('id'), messages.getAttribute('date'));
				}

				var messages = messages.childNodes;

				for (var j = 0; j < messages.length; j++)
				{
					var message = messages[j];
					chat.template.addMessage(message.getAttribute('id'), message)
					chat.updater.lastMessageID = message.getAttribute('id');
				}
			}
		}
	},

	postingEngine: {
		running: false,

		construct: function()
		{
			// :)
		},

		// Should be called by the template
		post: function(form)
		{
			if (!window.XMLHttpRequest)
			{
				// Continue without AJAX.
				return true;
			}

			if (chat.postingEngine.running)
			{
				alert(chat.lang.engineRunning);
				return false;
			}

			if (!form.message.value)
			{
				alert(chat.lang.emptyMessage);
				return false;
			}

			chat.postingEngine.running = true;

			if (chat.template.onMessageSent)
			{
				chat.template.onMessageSent();
			}

			var XHR = chat.XHR = new XMLHttpRequest();
			XHR.handleResponse = chat.postingEngine.handleResponse;
			XHR.onreadystatechange = chat.onXHRReadyStateChange;

			XHR.open('POST', form.action, true);
			XHR.setRequestHeader('Accept', 'application/x-oapi-response+xml,application/xml;q=0.5');
			XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			XHR.send(form.serializeInput());

			return false;
		},

		handleResponse: function(response)
		{
			chat.postingEngine.running = false;

			if (chat.template.onMessagePosted)
			{
				chat.template.onMessagePosted();
			}

			if (response.type == 'OK')
			{
				if (chat.template.onMessagePostedSuccessfully)
				{
					chat.template.onMessagePostedSuccessfully(response);
				}

				chat.updater.checkForChanges();
			}
			else
			{
				if (chat.template.onPostingErrorOccured)
				{
					chat.template.onPostingErrorOccured(response);
				}

				if (response.type = 'UserError')
				{
					alert(response.textContent);
				}
				else
				{
					alert(chat.lang.scriptErrorOccured + ' ' + response.textContent);
				}
			}
		}
	},

	actionEngine: {
		construct: function()
		{
			var actionsElements = chat.template.messages.getElementsByClassName('chat_actions');
			for (var i = 0; i < actionsElements.length; i++)
			{
				var actions = actionsElements[i].getElementsByTagName('a');
				for (var j = 0; j < actions.length; j++)
				{
					actions[j].onclick = this.runAction;
				}
			}
		},

		runAction: function()
		{
			// this == .chat_actions > a

			switch (this.textContent.trim())
			{
				case 'x':
					this.type = 'delete';
					var confirmMsg = chat.lang.confirmDelete;
				break;
			}

			if (!confirm(confirmMsg))
			{
				return false;
			}

			chat.actionEngine.running = true;

			if (chat.template.onActionSent)
			{
				chat.template.onActionSent();
			}

			var XHR = chat.XHR = new XMLHttpRequest();
			XHR.action = this; // Copy it, so we will know which action are we running.
			XHR.handleResponse = chat.actionEngine.handleResponse;
			XHR.onreadystatechange = chat.onXHRReadyStateChange;

			XHR.open('GET', this.href, true);
			XHR.setRequestHeader('Accept', 'application/x-oapi-response+xml,application/xml;q=0.5');
			XHR.send(null);

			return false;
		},

		handleResponse: function(response)
		{
			chat.actionEngine.running = false;

			if (chat.template.onActionDone)
			{
				chat.template.onActionDone(this.action);
			}

			if (response.type == 'OK')
			{
				if (chat.template.onActionDoneSuccessfully)
				{
					chat.template.onActionDoneSuccessfully(this.action, response);
				}

				alert(response.textContent);

				switch (this.action.type)
				{
					case 'delete':
						var messageID = response.getAttributeNS('http://phpbb3.pl/xmlns/Chat/MessageDeleted', 'messageID');
						chat.template.deleteMessage(messageID);
					break;
				}
			}
			else
			{
				if (chat.template.onActionErrorOccured)
				{
					chat.template.onActionErrorOccured(this.action, response);
				}

				if (response.type = 'UserError')
				{
					alert(response.textContent);
				}
				else
				{
					alert(chat.lang.scriptErrorOccured + ' ' + response.textContent);
				}
			}
		}
	}
};

Element.prototype.serializeInput = function()
{
	var serializedInput;

	var listOfChildren = [
		this.getElementsByTagName('input'),
		this.getElementsByTagName('textarea'),
		this.getElementsByTagName('select')
	];

	var children;
	for (children in listOfChildren)
	{
		children = listOfChildren[children];

		for (var i = 0; i < children.length; i++)
		{
			var child = children[i];

			if (!child.name || !child.value)
			{
				continue;
			}

			var serializedChild = child.name + '=' + encodeURIComponent(child.value);

			if (!serializedInput)
			{
				serializedInput = serializedChild;
			}
			else
			{
				serializedInput += '&' + serializedChild;
			}
		}
	}

	return serializedInput;
};

/*
// IE fix
if (!Element.prototype.addEventListener)
{
	Element.prototype.addEventListener = function(type, listener, useCapture)
	{
		this.attachEvent('on' + type, listener);
	}
}
*/

if (!Element.prototype.getElementsByClassName)
{
	Element.prototype.getElementsByClassName = function(name)
	{
		var classElements = new Array();
		var elements = this.getElementsByTagName('*');
		var pattern = new RegExp("(^|\\s)" + name + "(\\s|$)");

		for (i = 0; i < elements.length; i++)
		{
			var element = elements[i];
			if (pattern.test(element.className))
			{
				classElements.push(element);
			}
		}
		return classElements;
	}
}

String.prototype.trim = function()
{
	return this.replace(/^\s+|\s+$/g, '');
}

/*
String.prototype.ltrim = function()
{
	return this.replace(/^\s+/, '');
}

String.prototype.rtrim = function()
{
	return this.replace(/\s+$/, '');
}
*/