(function()
{
	Common.Object.create('Typical.Chat.RoomWindow.Messages', {

		roomWindow : null,
		
		elements : null,
		
		lastSentMessageDates : null,
		
		kicked : false,
		
		smilies : [
				   	[':|', ':-|'],
					[':(', ':-('],
					[':d', ':-d'],
					[':)', ':-)'],
					[':o', ':-o'],
					[';)', ';-)'],
					['0:)', '(A)', '(a)'],
					[':\'(', ':-\'('],
					['(6)'],
					['8)', '8-)'],
					[':D', ':-D'],
					['(k)', '(K)']
		],
		
		typNotification : 'Typ hier jouw berichtje!',

		Messages : function(roomWindow, container)
		{
			this.roomWindow = roomWindow;
			
			this.roomWindow.onConnect.add(this.handleConnect, this);
			
			this.initGUI(container);
			
			this.lastSentMessageDates = [];
			
			var chat = roomWindow.getChat();
			
			chat.onUserLoggedIn.add(this.checkUserLoggedIn, this);
			chat.onUserLoggedOut.add(this.checkUserLoggedIn, this);
			
			this.roomWindow.onBlur.add(this.handleWindowBlur, this);
			this.roomWindow.onFocus.add(this.handleWindowFocus, this);
			
			this.roomWindow.getChat().getConnector().onCmd('kicked', this.handleKicked.bind(this));
		},
		
		initGUI : function(container)
		{
			this.elements = {
								element : Builder.node('div', {className : 'typical chat roomwindow messages'}),
								messages : Builder.node('div', {className : 'messages'}),
								input : {
									element : Builder.node('div', {className : 'input'}),
									messageContainer : Builder.node('div', {className : 'messagecontainer'}),
									messageInput : Builder.node('input', {className : 'message invalid', maxlength : 200, value : this.typNotification}),
									login : null,
									connecting : Builder.node('div', {className : 'connecting'}, 'Bezig met laden..'),
									smilieButton : Builder.node('img', {className : 'smilies', src : Config.baseUrl + 'external/image/typical/chat/roomwindow/messages/smilies.png'}),
									sendButton : Builder.node('img', {className : 'send disabled', src : Config.baseUrl + 'external/image/typical/chat/roomwindow/messages/send.png'})
								}
							};
							
			Element.insert(this.elements.input.messageContainer, this.elements.input.messageInput);	

			Element.insert(this.elements.input.element, this.elements.input.smilieButton);	
			Element.insert(this.elements.input.element, this.elements.input.messageContainer);
			Element.insert(this.elements.input.element, this.elements.input.sendButton);	
			Element.insert(this.elements.input.element, this.elements.input.connecting);
			
			Element.insert(this.elements.element, this.elements.messages);
			Element.insert(this.elements.element, this.elements.input.element);
			
			// Init smilies window.
			this.elements.input.smiliesWindow = Builder.node('div', {className : 'smilieswindow'});
			{
				for(var smilieIndex = 0; smilieIndex < this.smilies.length; smilieIndex++)
				{
					var smilieElement = Builder.node('img', {className : 'smilie', src : Config.baseUrl + 'external/image/common/compose/smilies/smiley' + (smilieIndex + 1) + '.png'});
					{
						Event.observe(smilieElement, 'click', this.handleSmilieWindowSmilieClick.bindAsEventListener(this, smilieIndex));	
					}
					Element.insert(this.elements.input.smiliesWindow, smilieElement);
				}
			}
			Element.insert(this.elements.input.element, this.elements.input.smiliesWindow);
			
			Element.setOpacity(this.elements.input.smilieButton, 0.5);
			Element.setOpacity(this.elements.input.sendButton, 0.5);
			
			// Listen for interaction.
			Event.observe(this.elements.input.smilieButton, 'click', this.handleSmilieButtonClick.bind(this));
			
			Event.observe(this.elements.input.messageInput, 'focus', this.handleMessageInputFocus.bind(this));
			Event.observe(this.elements.input.messageInput, 'change', this.handleInputUpdate.bindAsEventListener(this));
			Event.observe(this.elements.input.messageInput, 'keydown', this.handleInputUpdate.bindAsEventListener(this));
			Event.observe(this.elements.input.messageInput, 'keyup', this.handleInputUpdate.bindAsEventListener(this));
			
			Event.observe(this.elements.input.sendButton, 'click', this.handleSendMessage.bind(this));
			
			// Add
			Element.insert(container, this.elements.element);
		},
		
		checkUserLoggedIn : function()
		{
			var loggedIn = this.roomWindow.getChat().userIsLoggedIn();
			
			// Show?
			if(!loggedIn && !this.elements.input.login)
			{
				// Make links.
				var linksTarget = Typical.SiteWrapper.getLinksTarget();
				
				var loginLink = Builder.node('a', {href : 'mijnprofiel/inloggen', target : linksTarget}, 'Log in');
				var registerLink = Builder.node('a', {href : 'mijnprofiel/baasjeworden', target : linksTarget}, 'registreer je');
				
				// Unfocus window by link.
				Event.observe(loginLink, 'click', this.roomWindow.blur.bind(this.roomWindow));
				Event.observe(registerLink, 'click', this.roomWindow.blur.bind(this.roomWindow));
				
				Element.setOpacity(this.elements.input.smilieButton, 0.5);
				
				// Make notification.
				this.elements.input.login = Builder.node('div', {className : 'login'}, ['Mee chatten? ', loginLink, ' of ', registerLink, ' nu!']);
				
				// Insert.
				Element.insert(this.elements.input.element, this.elements.input.login);
			}
			else if(loggedIn && this.elements.input.login)
			{
				// Hide
				Element.remove(this.elements.input.login);
				
				Element.setOpacity(this.elements.input.smilieButton, 1);
			
				this.elements.input.login = null;
			}
		},
		
		welcomMessageShowed : false,
		
		handleWindowFocus : function()
		{
			// Show welcome message?
			if(!this.welcomMessageShowed)
			{
				this.addSystemMessage({message : ['Welkom op de chat van ', Builder.node('b', 'SmartPets'), '! Wanneer iemand zich niet gedraagt, mag \'ie niet meer meepraten. Vertel nooit waar je woont en geef nooit wachtwoorden. Veel plezier!']});
			
				this.welcomMessageShowed = true;
			}
			
			if(this.elements.input.messageInput.value == this.typNotification)
				return;
				
			// Scroll down.
			this.elements.messages.scrollTop = 10000;
			
			// Focus input.
			(function()
			{
				try
				{
					this.elements.input.messageInput.focus();
				}
				catch(e)
				{
				}
			}).bind(this).delay(1);
		},
		
		handleMessageInputFocus : function()
		{
			if(this.elements.input.messageInput.value != this.typNotification)
			 	return;
			
			Element.removeClassName(this.elements.input.messageInput, 'invalid');
			
			this.elements.input.messageInput.value = '';
		},
		
		handleInputUpdate : function(event)
		{
			if(event && event.keyCode == 13)
				this.handleSendMessage();
			
			else
			{
				var valid = this.elements.input.messageInput.value != '' ;
				
				if(valid)
					Element.removeClassName(this.elements.input.sendButton, 'disabled');
				
				else
					Element.addClassName(this.elements.input.sendButton, 'disabled');
					
				Element.setOpacity(this.elements.input.sendButton, valid ? 1 : 0.5);
			}
		},
		
		handleConnect : function()
		{
			// Hide connect message.
			if(this.elements.input.connecting)
			{
				Element.remove(this.elements.input.connecting);
			
				this.elements.input.connecting = null;
				
				Element.setOpacity(this.elements.input.smilieButton, 1);
			}
			
			this.checkUserLoggedIn();
			
			this.roomWindow.getChannel().onCmd('userMessage', this.handleNewMessage.bind(this));
		},
		
		floodWarned : false,
		
		handleSendMessage : function()
		{
			if(!this.roomWindow.getChat().userIsLoggedIn())
				return;
			
			var message = this.elements.input.messageInput.value;
			
			if(message == '' || message == this.typNotification)
				return;
			
			while(this.lastSentMessageDates.first() && this.lastSentMessageDates.first().getTime() + 5 * 1000 <= new Date().getTime())
				this.lastSentMessageDates.shift();
				
			// Check flooding.
			if(this.lastSentMessageDates.length >= 5)
			{
				if(!this.floodWarned)
					this.addSystemMessage({message : 'Je mag niet zo snel praten. Eventjes wachten dus.'});
				
				this.floodWarned = true;
			}
			else
			{
				this.floodWarned = false;
				
				this.lastSentMessageDates.push(new Date());
				
				this.elements.input.messageInput.value = '';
				
				this.handleInputUpdate();
				
				this.roomWindow.getChannel().send('userMessage', {message : message});
				
				this.handleNewMessage({
										message : message
									  });
			}
		},
		
		addSystemMessage : function(messageData)
		{
			this.addMessageElement(Builder.node('div', {className : 'systemmessage' + (messageData.type ? ' ' + messageData.type : '')}, messageData.message));
		},
		
		handleNewMessage : function(messageData)
		{
			var ownUserData = this.roomWindow.getChat().getUserData();
			
			var userData = ownUserData;
			
			if(userData && userData.id == messageData.userId)
				return;
			
			// Message of someone else?
			else if(!userData || messageData.userId && userData.id != messageData.userId)
			{
				userData = this.roomWindow.getUserData(messageData.userId);
				
				this.roomWindow.onUnfocussedActivity.dispatch();
			}
			
			// User data not present (yet)?
			if(!userData)
				userData = {username : '?', avatarExtension : null};
			
			// Kicked?
			var kickElement = '';
			
			if(ownUserData && ownUserData.isModerator && ownUserData != userData /**&& @todo !userData.isModerator**/)
			{
				kickElement = Builder.node('div', {className : 'kick'}, 'Verbied praten');
				
				Event.observe(kickElement, 'click', this.handleKick.bindAsEventListener(this, userData));
			}
			
			// Smilies.
			messageData.message = messageData.message.escapeHTML();
			
			for(var smilieIndex = 0; smilieIndex < this.smilies.length; smilieIndex++)
			{
				for(var i = 0; i < this.smilies[smilieIndex].length; i++)
					messageData.message = messageData.message.split(this.smilies[smilieIndex][i]).join('<img src="' + Config.baseUrl + 'external/image/common/compose/smilies/smiley' + (smilieIndex + 1) + '.png" />');
			}
			
			var messageElement = Builder.node('div', {className : 'message'});
			
			messageElement.innerHTML = messageData.message;
			
			// Add message.
			this.addMessageElement(	Builder.node('div', {className : 'messagecontainer'}, [
										Builder.node('img', {src : Config.baseUrl + 'external/image/profile/avatar/' + (userData.avatarExtension ? userData.id + '.' + userData.avatarExtension : 'standard.jpg'), className : 'avatar'}),
										userData.isVIP ? Builder.node('img', {className : 'vip', title : 'Is Very Important Petter.' /* @todo */, src : Config.baseUrl + 'external/image/typical/chat/roomwindow/users/vip.png'}) : '',
										userData.isModerator ? Builder.node('img', {className : 'moderator', title : 'Is moderator en zorgt dus voor een veilige chat.' /* @todo */, src : Config.baseUrl + 'external/image/typical/chat/roomwindow/users/moderator.png'}) : '',
										Builder.node('div', {className : 'author'}, [
											Builder.node('a', {href : 'profiel/' + userData.username, target : 'mainframe', className : 'profile'}, userData.username),
											' zegt:', kickElement]),
										messageElement
									])
								   );
		},
		
		addMessageElement : function(messageElement)
		{
			var shouldScroll = (this.elements.messages.scrollHeight - this.elements.messages.scrollTop - Element.getHeight(this.elements.messages)) == 0;
			
			// Construct and show.
			Element.insert(this.elements.messages, messageElement);
			
			// Remove?
			if(this.elements.messages.childNodes.length > 25)
				Element.remove(this.elements.messages.firstChild);
				
			if(shouldScroll)
				this.elements.messages.scrollTop = 10000;
		},
		
		handleKick : function(event, userData)
		{
			var hours = prompt('Hoeveel uur wil je "' + userData.username + '" stil hebben?');
			
			if(!hours || isNaN(parseInt(hours)) || parseInt(hours) <= 0)
				return;
				
			this.roomWindow.getChat().getConnector().request('kickUser', {userId : userData.id, hours : hours}, function(data)
			{
				if(data.success)
					this.addSystemMessage({
											message : Builder.node('font', ['Je hebt ', Builder.node('b', userData.username), ' succesvol het meepraten voor ', Builder.node('b', data.hours), ' uren verboden.'])
										  });
			}.bind(this));
		},
		
		handleKicked : function(data)
		{
			this.kicked = true;
			
			var message;
			
			if(this.elements.input.connecting)
			{
				Element.remove(this.elements.input.connecting);
			
				this.elements.input.connecting = null;
				
				Element.setOpacity(this.elements.input.smilieButton, 0.5);
				Element.setOpacity(this.elements.input.sendButton, 0.5);
			}
			
			if(data.hours <= 1)
				message = 'Je mag binnen een uur weer meepraten. Dit scherm sluit zo vanzelf.'
				
			else
				message = 'Je mag de komende ' + data.hours + ' uren niet meepraten. Dit scherm sluit zo vanzelf';
			
			this.addSystemMessage({
									message : message
								  });	
			
			this.elements.input.messageInput.value = '';
			this.elements.input.messageInput.disabled = true;
			
			setTimeout(function()
			{
				this.roomWindow.getChat().close();
			}.bind(this), 10 * 1000);
		},
		
		handleSmilieButtonClick : function()
		{
			if(!Element.hasClassName(this.elements.input.smiliesWindow, 'opened'))
			{
				if(this.elements.input.connecting == null && !this.kicked)
					Element.addClassName(this.elements.input.smiliesWindow, 'opened');
			}
			else
				Element.removeClassName(this.elements.input.smiliesWindow, 'opened');
		},
		
		handleSmilieWindowSmilieClick : function(event, smilieIndex)
		{
			// Hide smilies dinwo.
			Element.removeClassName(this.elements.input.smiliesWindow, 'opened');
			
			if(this.elements.input.messageInput.value == this.typNotification)
			{
				this.elements.input.messageInput.value = '';
				
				Element.removeClassName(this.elements.input.messageInput, 'invalid');
			}
			
			this.elements.input.messageInput.value += this.smilies[smilieIndex][0];
			
			this.elements.input.messageInput.focus();
			
			this.handleInputUpdate();
		},
		
		handleWindowBlur : function()
		{
			// Hide smilies window.
			Element.removeClassName(this.elements.input.smiliesWindow, 'opened');
		}
		
	});
})();
