/**
 * Main JavaScript class for the chat
 *
 * @author		Tim Düsterhus
 * @copyright	2010 Tim Düsterhus
 * @package		timwolla.wcf.chat
 * @license		Creative Commons BY-NC-ND <http://creativecommons.org/licenses/by-nc-nd/3.0/de/>
 */

var Chat = Class.create();
Chat.prototype = {
	initialize: function(id, reloadtime, prefix) {
		// set defaults
		this.id = 0;
		this.reloadtime = 5;
		this.prefix = 'chat';
		this.loading = false;
		this.autoscroll = true;
		this.users = new Array();
		this.privateChannels = new Array();
		this.activeUserID = 0;
		this.activeUsername = '';
		this.menuStatus = new Array();
		this.enableAnimating = false;
		this.enableAutoComplete = true;
		this.showText = false;
		this.titleAnimator = null;
		this.text = document.title;
		this.noText = htmlEntityDecode('&nbsp;');
		if (settings['timeout'] > 0) this.timeoutTimer = window.setTimeout(this.kill.bind(this), settings['timeout'] * 60 * 1000);

		// remove the initializing bar
		$(this.prefix+'Initializing').fade({duration: 1});

		// add the main channel
		this.privateChannels[0] = 0;

		// sets the current ID
		this.id = id;

		// sets the prefix for the elements
		this.prefix = prefix;

		// register events
		var observeWindow = document;
		if (Prototype.Browser.IE) observeWindow = window;
		Event.observe(observeWindow, 'focus', this.stopAnimating.bind(this));

		Event.observe($(this.prefix+'Form'), 'submit', this.submitHandler.bind(this));

		Event.observe($(this.prefix+'Input'), 'keydown', this.keydownHandler.bind(this));
		Event.observe(observeWindow, 'keydown', this.refreshHandler.bind(this));

		// load messages
		this.getMessages();
		new PeriodicalExecuter(this.getMessages.bind(this), reloadtime);

		if (settings['animation']) {
			// scroll down in a smooth animation
			new PeriodicalExecuter(function () {
				// Scroll only if the user wants to
				if (this.autoscroll) {
					for (var i = 0; i < this.privateChannels.length; i++) {
						$(this.prefix+'Message'+this.privateChannels[i]).scrollTop = (($(this.prefix+'Message'+this.privateChannels[i]).scrollTop < $(this.prefix + 'Message'+this.privateChannels[i]).scrollHeight) ? $(this.prefix+'Message'+this.privateChannels[i]).scrollTop + 10 : $(this.prefix+'Message'+this.privateChannels[i]).scrollHeight);
					}
				}
			}.bind(this), .1);
		}
	},
	keydownHandler: function(event) {
		if (!event) {
			event = window.event;
		}

		if (event.which) {
			keynumber = event.which;
		} 
		else if (event.keyCode) {
			keynumber = event.keyCode;
		}
		// autocompletion
		if (keynumber == 9 && this.enableAutoComplete) {
			length = $(this.prefix+'Input').value.length;
			split = $(this.prefix+'Input').value.split(" ");
			for (var i = 0; i < this.users.length; i++) {
				if (split[(split.length - 1)].length > 0 && (split[(split.length - 1)] == this.users[i].substr(0,split[(split.length - 1)].length))) {
					$(this.prefix+'Input').value += this.users[i].substr(split[(split.length - 1)].length) + ' ';
					break;
				}
			}

			$(this.prefix+'Input').focus();
			$(this.prefix + 'Input').selectionStart = length;
			$(this.prefix + 'Input').selectionEnd = $(this.prefix + 'Input').value.length;
			event.stop();
		}
		else if(keynumber == 13 && this.enableAutoComplete) {
			if ($(this.prefix + 'Input').selectionStart < $(this.prefix + 'Input').selectionEnd) {
				$(this.prefix + 'Input').selectionStart = $(this.prefix + 'Input').selectionEnd = $(this.prefix + 'Input').value.length;
				event.stop();
			}
		}
	},
	refreshHandler: function(event) {
		if (!event) {
			event = window.event;
		}

		if (event.which) {
			keynumber = event.which;
		} 
		else if (event.keyCode) {
			keynumber = event.keyCode;
		}
		// autocompletion
		if (keynumber == 116) {
			event.stop();
			this.kill = function () { };
			new Ajax.Request('index.php?form=Chat&kill=1'+SID_ARG_2ND, { method: 'get', onSuccess: function () { window.location.href = 'index.php?page=Chat'+SID_ARG_2ND }, onFailure: function () { window.location.href = 'index.php?page=Chat'+SID_ARG_2ND } });
		}
	},
	submitHandler: function(event) {
		if (!$(this.prefix+'Input').value.blank()) {
			if (this.activeUsername != '') {
				$(this.prefix + 'Input').value = '/whisper "' + this.activeUsername + '" '+$(this.prefix + 'Input').value;
			}
			$(this.prefix + 'Form').request({ parameters: { ajax:'1' }, onSuccess: this.getMessages.bind(this) });
		}
		$(this.prefix + 'Input').clear();
		if (event) event.stop();
		$(this.prefix + 'Input').focus();

		if (settings['timeout'] > 0) {
			// set timers for automatic timeout
			if (this.timeoutTimer) window.clearTimeout(this.timeoutTimer);
			this.timeoutTimer = window.setTimeout(this.kill.bind(this), settings['timeout'] * 60 * 1000);
		}
	},
	isOpenChannel: function (id) {
		for (var j = 0; j < this.privateChannels.length; j++) {
			if (this.privateChannels[j] == id) {
				return true;
			}
		}
		return false;
	},
	stopAnimating: function () {
		if (this.titleAnimator != null) {
			this.titleAnimator.stop();
			Sound.disable();
			document.title = this.text;
		}
	},
	animate: function () {
		if (!Prototype.Browser.WebKit && !document.hasFocus()) {
			if (this.titleAnimator != null) {
				this.titleAnimator.stop();
			}
			Sound.enable();
			Sound.play(RELATIVE_WCF_DIR + 'js/chat.mp3');
			this.titleAnimator = new PeriodicalExecuter(this.toggleTitle.bind(this), 1);
		}
	},
	toggleTitle: function (pe) {
		if (this.showText) {
			document.title = this.text;
			this.showText = false;
		}
		else {
			document.title = this.noText;
			this.showText = true;
		}
	},
	getMessages: function () {
		if (this.loading == false) {
			$(this.prefix + 'Loading').style.display = 'inline';
			this.loading = true;
			new Ajax.Request('index.php?page=ChatMessage&id='+this.id+SID_ARG_2ND, {
				method: 'get',
				onSuccess: this.update.bind(this),
				onFailure: this.failure.bind(this),
				sanitizeJSON: true
			});
		}
	},
	failure: function () {
		this.kill = function () { };
		$(this.prefix+'Error').appear({duration: 1});
	},
	update: function (transport) {
		this.loading = false;
		$$('#'+this.prefix+'ExtraRoomContainer select')[0].enable();
		$(this.prefix + 'Loading').style.display = 'none';

		var json = transport.responseJSON;
		this.handleUserUpdate(json.users, json.permissions);
		this.handleMessageUpdate(json.messages);
	},
	handleUserUpdate: function (users, permissions) {
		var ul = new Element("ul");
		ul.setStyle({listStyle: 'none'});
		var userlist = '';
		this.users = new Array();
		var size = users.length;
		for (var i = 0; i < size; i++) {
			this.users[this.users.length] = users[i].usernameraw;
			var li = new Element('li');
			var a = new Element('a', { 'id': this.prefix + 'UserListItem'+i });
			Event.observe(a, 'click', this.openList.bind(this));
			if (users[i].muted == 1) {
				// if the user is muted he will be striked
				a.setStyle({textDecoration: 'line-through'});	
			}
			// users that are marked as away are display italic
			if (users[i].away != '') {
				a.title = users[i].away;
				a.setStyle({fontStyle: 'italic'});
			}
			a.update(users[i].username);
			li.insert(a);
			var actions = new Element("ul");

			if (this.menuStatus[users[i].usernameraw] == true) { 
				/* do nothing */ 
			} 
			else {
				actions.setStyle({display: 'none'});
			}
			// Profile
			action = new Element('li');
			actionhref = new Element('a');
			actionhref.update(language['wcf.chat.profile']);
			actionhref.href = 'index.php?page=User&userID='+users[i].userID;
			action.insert(actionhref);
			actions.insert(action);
			if (users[i].away == '') {
				// Whisper insert
				action = new Element('li');
				actionhref = new Element('a');
				actionhref.update(language['wcf.chat.whisperjs']);
				actionhref.username = users[i].usernameraw;
				Event.observe(actionhref, 'click', this.insertwhisper.bind(this));
				action.insert(actionhref);
				actions.insert(action);
				// Private insert
				action = new Element('li');
				actionhref = new Element('a');
				actionhref.update(language['wcf.chat.private']);
				actionhref.userid = users[i].userID;
				actionhref.username = users[i].usernameraw;
				Event.observe(actionhref, 'click', this.openPrivate.bind(this));
				action.insert(actionhref);
				actions.insert(action);
			}
		/*	if(permissions.canMute == 1 && users[i].muted == 0) { 
				// Mute insert
				action = new Element('li');
				command = '/mute '+users[i].username+' ';
				actionhref = new Element('a', { href: 'javascript:void(chat.insert("'+command+langvars['wcf.chat.timeinminutes']+'", false, '+command.length+', '+langvars['wcf.chat.timeinminutes'].length+'))' });
				actionhref.update(langvars['wcf.chat.mute']);
				action.insert(actionhref);
				actions.insert(action);
			}
			if(permissions.canUnMute == 1 && users[i].muted == 1) { 
				// Unmute insert
				action = new Element('li');
				command = '/unmute '+users[i].username+' ';
				actionhref = new Element('a', { href: 'javascript: chat.insert("'+command+'", false, 0, 0, true);' });
				actionhref.update(langvars['wcf.chat.unmute']);
				action.insert(actionhref);
				actions.insert(action);
			}
			if(permissions.canBan == 1) { 
				// Ban insert
				action = new Element('li');
				command = '/ban '+users[i].username+' ';
				actionhref = new Element('a', { href: 'javascript:void(chat.insert("'+command+langvars['wcf.chat.timeinminutes']+'", false, '+command.length+', '+langvars['wcf.chat.timeinminutes'].length+'))' });
				actionhref.update(langvars['wcf.chat.ban']);
				action.insert(actionhref);
				actions.insert(action);
			} */
			li.insert(actions);
			ul.insert(li);
		}
		$$('#chatMembers ul')[0].remove();
		$('chatMembers').insert(ul);
	},
	handleMessageUpdate: function (messages) {
		var size = messages.length;
		if (size > 0 && this.enableAnimating && !Prototype.Browser.Opera) {
			this.animate();
		}

		this.id = messages[size - 1].id;
		for (var i = 0; i < size; i++) {
			var li = new Element('li');
			if (messages[i].type == 1 || messages[i].type == 2) {
				// important messages are bold and italic
				li.setStyle({fontWeight: 'bold', fontStyle: 'italic'});
				var name = messages[i].username + ' ';
			}
			else if (messages[i].type == 3) {
				var name = messages[i].username + ' ';
			}
			else if (messages[i].type == 4) {
				// type 4 is clearing the chat
				$(this.prefix + 'Message0').update('<ul style="list-style:none;"><li>&nbsp;</li></ul>');
				li.setStyle({fontWeight: 'bold', fontStyle: 'italic'});
				var name = messages[i].username + ' ';
			}
			else if (messages[i].type == 5) {
				// global annoucements
				li.setStyle({fontWeight: 'bold', fontStyle: 'italic'});
				var name = messages[i].username + ' ' + language['wcf.chat.global'] + ' ';
			}
			else if (messages[i].type == 6) {
				// team annoucements
				li.setStyle({fontWeight: 'bold', fontStyle: 'italic'});
				var name = messages[i].username + ' ' + language['wcf.chat.team'] + ' ';
			}
			else {
				var name = messages[i].username + ': ';
			}
			name = '<span style="font-weight: bold;">'+name+'</span>';
			li.innerHTML = '<input type="checkbox" value="' + messages[i].id + '" style="display: none;' + (settings['align'] == 'center' ? ' float:left' : '') + '" />' + (settings['align'] == 'center' ? '<div class="formElement"><div class="formFieldLabel"><div style="float:left">' : '') + messages[i].time + (settings['align'] == 'center' ? '</div>' : '') + ' ' + name  + (settings['align'] == 'center' ? '</div><div class="formField" style="margin-left: 203px;">' : ' ') + messages[i].text;
			if (settings['align'] == 'center') li.innerHTML += '</div></div><div style="clear:both"></div>';

			if (settings['animation']) li.setStyle({ display: 'none' });

			if (this.isOpenChannel(messages[i].privateID)) {
				// private channel
				if (messages[i].privateID != 0) {
					li.innerHTML =  li.innerHTML;
				}
				
				$$('#'+this.prefix+'Message'+messages[i].privateID+' ul')[0].insert(li);
				if (settings['animation']) li.appear({ duration: .4 });
				if (this.activeUserID != messages[i].privateID) {
					// mark as new if not in this channel
					$$('#'+this.prefix+'Private'+messages[i].privateID+' a')[0].addClassName('importantPrivate');
				}
			}
			else {
				$$('#'+this.prefix+'Message0 ul')[0].insert(li);
				if (settings['animation']) li.appear({ duration: .4 });
				if (this.activeUserID != 0) {
					$$('#'+this.prefix+'Private0 a')[0].addClassName('importantPrivate');
				}
			}
		}

		// Scroll only if the user wants
		if (this.autoscroll && !settings['animation']) {
			for (var i = 0; i < this.privateChannels.length; i++) {
				$(this.prefix+'Message'+this.privateChannels[i]).scrollTop = $(this.prefix + 'Message'+this.privateChannels[i]).scrollHeight;
			}
		}
	},
	openList: function (event) {
		e = Event.element(event);
		e2 = e;
		if(e.tagName != 'A') {
			e = e.up('a');
		}
		if(e.parentNode.getElementsByTagName('ul')[0].style.display == 'none') {
			e.parentNode.getElementsByTagName('ul')[0].blindDown();
			id = e2.innerHTML; 
			this.menuStatus[id] = true;
		}
		else {
			e.parentNode.getElementsByTagName('ul')[0].blindUp();
			id = e2.innerHTML; 
			this.menuStatus[id] = false;
		}
	},
	empty: function () {
		$(this.prefix + 'Message'+this.activeUserID).update('<ul style="list-style:none;"><li>&nbsp;</li></ul>');
	},
	kill: function () {
		new Ajax.Request('index.php?form=Chat&kill=1'+SID_ARG_2ND, { method: 'get' });
	},
	insert: function (value, append, selectFrom, selectLength, submit) {
		if (append) {
			$(this.prefix + 'Input').value += value;
		}
		else {
			$(this.prefix + 'Input').value = value;
		}

		selectFrom = selectFrom || 0;
		if (selectFrom > 0) {
			$(this.prefix + 'Input').selectionStart = selectFrom;
			$(this.prefix + 'Input').selectionEnd = selectLength + selectFrom;
		}

		if (submit) {
			this.submitHandler();
		}
		else {
			$(this.prefix + 'Input').focus();
		}
	},
	insertSmiley: function (code) {
		this.insert(' '+code+' ', true);
	},
	insertwhisper: function (name) {
		name = Event.element(name).username;
		this.insert('/whisper "' +name+'" ', false);
	},
	getAllChecked: function () {
		var ids = '';
		$$('#' +this.prefix + 'Message'+this.activeUserID+' > ul > li > input[type=checkbox]').each(function (e) { 
			if (e.checked) { 
				if(ids.empty()) { 
					ids += e.value;
				} 
				else { 
					ids += ','+e.value;
				} 
			} 
		});
		return ids;
	},
	displayCheckBoxes: function () {
		$$('#' +this.prefix + 'Message'+this.activeUserID+' > ul > li > input[type=checkbox]').each(function (e) { 
			e.setStyle({ display: '' });
		});
	},
	clearCheckBoxes: function () {
		$$('#' +this.prefix + 'Message'+this.activeUserID+' > ul > li > input[type=checkbox]').each(function (e) { 
			e.checked = false; 
			e.setStyle({ display: 'none' });
		});
	},
	openPrivate: function (userID, username) {
		if(typeof userID == 'object') {
			e = Event.element(userID);
			username = e.username;
			userID = e.userid;
		}

		var notFound = !this.isOpenChannel(userID);
		if (this.privateChannels.length == 1) {
			// display the main tab if it is not
			$(this.prefix + 'Private0').setStyle({display: ''});
		}
		if (notFound) {
			// create new tab
			this.privateChannels[this.privateChannels.length] = userID;
			li = new Element("li", {id: this.prefix + 'Private'+userID});
			a = new Element("a");
			a.userid = userID;
			a.username = username;
			Event.observe(a, 'click', this.openPrivate.bind(this));
			a.update(username);
			li.insert(a);
			$(this.prefix + 'Privatelist').insert(li);
			box = new Element('div',  { id: this.prefix + 'Message'+userID });
			box.addClassName('color-2');
			box.setStyle({ display: 'none'});
			ul = new Element('ul');
			ul.setStyle({listStyle: 'none'});
			li = new Element('li');
			li.update('&nbsp;');
			ul.insert(li);
			box.insert(ul);
			$(this.prefix + 'Message').insert(box);
			chat.openPrivate(userID, username);
		}
		else {
			// display existing tab
			if (userID == 0) {
				$(this.prefix + 'Members').removeClassName('hidden');
				$(this.prefix + 'PrivateControl').addClassName('hidden');
				$(this.prefix + 'ExtraRoomContainer').setStyle({display: ''});
				$$('#'+this.prefix + 'Options img')[0].setStyle({display: ''});
			}
			else {
				$(this.prefix + 'Members').addClassName('hidden');
				$(this.prefix + 'PrivateControl').removeClassName('hidden');
				$(this.prefix + 'ExtraRoomContainer').setStyle({display: 'none'});
				$$('#'+this.prefix + 'Options img')[0].setStyle({display: 'none'});
			}
			$(this.prefix + 'Private' + this.activeUserID).removeClassName('activeSubTabMenu');
			$(this.prefix + 'Private' + userID).addClassName('activeSubTabMenu');
			$$('#'+this.prefix + 'Private' + userID +' a')[0].removeClassName('importantPrivate');
			$(this.prefix + 'Message' + this.activeUserID).setStyle({display: 'none'});
			$(this.prefix + 'Message' + userID).setStyle({display: ''});
			this.activeUserID = userID;
			this.activeUsername = username;
		}
		$(this.prefix+'Input').focus();
	},
	closePrivate: function (userID) {
		userID = userID || this.activeUserID;
		privateChannels = new Array();
		for (var i = 0; i < this.privateChannels.length; i++) {
			if (this.privateChannels[i] != userID) {
				privateChannels[privateChannels.length] = this.privateChannels[i];
			}
		}
		this.privateChannels = privateChannels;
		$(this.prefix + 'Private'+userID).remove();
		$(this.prefix + 'Message'+userID).remove();
		this.activeUserID = 0;
		this.openPrivate(0, '');
	},
	changeRoom: function (roomID, username) {
		if (!$$('#'+this.prefix+'ExtraRoomContainer select')[0].disabled) {
			$$('#'+this.prefix+'ExtraRoomContainer select')[0].disable();
			chat.loading = true;
			if (username != '') username = '&username='+username;
			new Ajax.Request('index.php?page=Chat'+SID_ARG_2ND+'&ajax=1&room=' + roomID + username,
			{
				onFailure: function () { $(this.prefix+'ErrorRoom').appear({ duration: 1 }); this.kill = function () { }; },
				onSuccess: function () {
					$('room'+roomID+'Option').selected = true;
					chat.loading = false;
				} 
			});
		}
	}
}
