/*
 * Copyright rphaven.com
 * Not for modification or use elsewhere 
 */
function convertNL(replace) {
	var i = 0;
	return function (str) {
		i++
		return i < 5 ? replace : str
	}
};
var two = function(x) {return ((x>9)?"":"0")+x};
function msToReadable(ms) {
	var sec = Math.floor(ms/1000);
	var min = Math.floor(sec/60);
	sec = sec % 60;	
	var hr = Math.floor(min/60);
	min = min % 60;
	hr = hr % 60;
	
	t = hr + ":" + two(min) + ":" + two(sec);
	
	return t;
}
function makeTimestamp(unixtime) {
	var date = unixtime ? new Date(unixtime * 1000) : new Date();
	var curDate = new Date();
	var monthsList = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
	var string = date.getHours() + ':' + two(date.getMinutes()) + ':' + two(date.getSeconds());
	var dateInt = date.getFullYear()+two(date.getMonth())+two(date.getDate());
	var curDateInt = curDate.getFullYear()+two(curDate.getMonth())+two(curDate.getDate());
	if( curDateInt > dateInt ){
		if( (curDateInt-dateInt) == 1 )
			string = "Yesterday, "+string;
		else
			string = monthsList[date.getMonth()]+" "+date.getDate()+", "+ string;
	}
    return string;
}

$(function() {
	
	//APE.Config.scripts.push(APE.Config.baseUrl+'/Source/Core/Session.js');
	client = new APE.Client();
	core = null;
	
	client.load({
		'domain': APE.Config.domain,
		'server': APE.Config.server,
		'identifier': 'rphchat',
		'channel': '*global',
		'complete': function(){
			core = client.core;
			chat.init();
			var updates = $('<div class="subAlert"><p style="font-size:15px;">I\'m still adding new features and fixing things.  Please donate if you can.<p></div>');
			updates.prependTo("#mainChat");
			updates.append( $('<p style="cursor:pointer;" class="news">Q4 2009 patch notes:</p>').append('<div style="font-size:12px;display:none;">11/22 Version 1.00.10 of the new chat. Some characters not working.  Link color in PM fixed so it can be seen.<br />11/22 Version 1.00.30 UI changed a little, last-login date on profiles updates when logging in to chat, html gets stripped from messages.  Fixed chrome momentary freezes.  Added notification when someone says your name.  Fixed PM to reopen when you get a message after it\'s closed(until I add a more proper minimize functionality).  However status for tooltip to see long ones.  Doesn\'t auto-scroll when you\'ve scrolled up to view history.  Too many minor things I forgot..<br />11/26 Version 1.00.50 Fixes to clickable link-converting.  Fix so it scrolls to bottom when you change PM tab.  Fix for messages with % in them not sending.  Fixed poor displaying on room join/create list when there were many rooms. Version 1.00.60 Blocking works on names with spaces now.<br />12/02 Version 1.10.00 Major update..<ul style="padding-left: 5px;"><li>Single click does nothing on userlist names now.  Doubleclick to open IM\'s instead.</li><li>Ignores save and restore.(max of 50 for non-donators, unlimited for donators.)</li><li>You can add users to buddylist.(max of 100 for non-donators, unlimited for donators)</li><li>There is a max length of 20 chars on status messages for non-donators, max of 100 for donators. (Too much bandwidth was being used.)</li></ul>12/03 Version 1.10.10 Fixed buddylist and donator specific things not working when there are spaces in name.  Fixed it so newly added buddys appear on list without needing to refresh.<br />12/08 Version 10.10.05 Fixed a bug with textarea not coming up on PM\'s with IE.  But theres a bug with it growing to max size on every keypress.  You.. shouldn\'t be using IE, seriously.  Use Firefox, Safari, Chrome.<br />12/12 Version 10.20.00 Fixed bug with creating room.  Should work fine now.(Edit: nevermind, I fixed two bugs with it but there is one more.  It\'s going to take a few days to fix the final one.. but it works a bit better now at least.)  Fixed new rooms you create appearing on the friends list instead of rooms list.  Bandwidth improvements with typing notification, messages.  Can now click to open pictures/youtubes in a dialog window.  Some buddy list fixes(it isn\'t fully working still though).<br />12/12 Version 10.30.00 Version control.  Improvements to speed of writing messages.  The \'is idle\' is now sent to people who have a window open for the person, not who the person has windows open for.  About 20% reduction to the amount of code.</div>')
				);
			updates.append( $('<p style="cursor:pointer;" class="news">Q1-Q2 2010 patch notes:</p>').append('<div style="font-size:12px;display:none;">01/19 Version 10.40.00 Major recoding to improve chat client performance(Should be 2-3x faster).  Also note that RPH is about 4x faster on Firefox, 5x faster on Chrome/Safari compared to IE6/IE7.<br /> 01/20 Version 10.40.10 HEY IT IS MY BIRTHDAY.  Also, fixed the top buttons on PM\'s not working in IE.  PS:  IE sucks.<br />01/23 Version 10.40.50 Some UI appearance changes and expanding/collapsing room lists just takes a single click now.<br />02/23 Version 10.70.00 Been a while since I updated this version.. So many changes I can\'t remember them.  When you make a room, you can now make people operators of it where you and them can kick and ban.  New code for the resizing chatlist/buddies/chat that\'s much faster/lighter, allows you to drag and rearrange them, and save the sizes.  Major improvements to make the chat not lag.  Some fixes to buddy list.  Fixes to lots of small bugs.<br />03/25 Version 10.75.00 Added support for permanent rooms/topics.  Fixed some small display bugs.</div>')
				);
			updates.append( $('<p style="cursor:pointer;" class="news">Q3-Q4 2010 patch notes:</p>').append('<div style="font-size:12px;display:none;">6/15 Version 10.76.00 - (Forgot to update this for a while, left out some changes/fixes. o_o)  Added dropdown menus for join/leave messages.  Fixed a rare bug where there would be empty rooms on the user list.  Fixed the bug where a dialog window would "jump" up halfway into the top of the window.<br />6/17 Version 10.77.00 Fixed the bug where colors and other settings wouldn\'t save.  Added the ability to unban(Manage button at the room\'s header) along with a more convenient place to change the topic at.<br />7/07 Version 11.00.00 Imageshare added.  7/13 Version 11.10.00 Group room settings update daily.  Co-owners and moderators are automatically set as owners and operators for the Group\'s permanent room..<br />8/02 Version 11.50.00 notify/pings are case sensitive now.  Fixed the bug with image-share which would insert empty images.<br />11/15 version 12.00.00 Fixed a bug where the first message sent to someone would often not be received.  Recoded the right-click dropdown lists for better performance and to add new features.</div>')
				);
			updates.append( $('<p style="cursor:pointer;" class="news">Q1-Q2 2011 patch notes:</p>').append('<div style="font-size:12px;display:none;">01/15 version 12.00.10 Right click menus now position correctly so there aren\'t any unclickable options.<br />01/31 version 12.00.20 Fixed some crashes that would happen on the chat server.<br />02/16 version 12.50.00 Much recoding to speed up the chat.  There is now a settings menu.  Sounds now use HTML5 playback instead of flash on browsers that support it.<br />02/18 version 13.00.00 Friends list improvements, and online group members are now shown on your friends list. Image-share has been fixed.<br />02/19 version 13.00.10 You can now remove people from your friends list.  Fixed usercount at the top.  Fixed being unable to rejoin a room after swifting rooms. Fixed pm not notifying user signoff. Fixed ignores.<br />02/22 version 13.50.00 Bans are now super effective.  Bans for group rooms are now saved between server resets. You can now hide your room from view.  Some other minor changes.<br />02/25 version 13.60.00 Fixed perm room bans to actually save correctly.  Fixed private rooms to actually be private.  Updated the Room Manage dialog to be better.  Room topic, and perm room group url, now shows upon joining a room.  Max room messages added to options(performance increase).<br />02/25 version 13.60.10 Bug fixes for last update.<br /> 03/22 version 13.70.00 Cleaned up some code to make way for adding offline messaging soon.  PM tabs now update when a user logs back on, rather than creating multiple ones for the same user.<br />03/26 version 13.80.00 Messages can now be sent to offline users.  Minor bug fixes done.<br />04/05 version 13.85.00 You can now join multiple rooms.  Fixed imageshare and adding friends not working.  Greatly reduced lag.<br />04/10 version 14.00.00 Multiple notify words can be added in settings.  PM\'s now only scroll when your current tab receives a message.  Updated scrolling to not fail when large messages are posted. Client-side message logging has been added(will be improved on later.).<br />04/11 version 14.10.00 Desktop notifications added for Chrome and some improvements to logging.<br />04/22 version 14.11.00 Some fixes to updating pm tab styling to reflect users status.  Repeated idle and login messages will group together now.  Efficiency improvements.<br />04/24 version 14.50.00 Added a looking-for-rp list and some minor changes to the chat server. version 14.50.20 bugfixes for the last update.<br />04/25 version 14.50.30 A notification will occasionally show when a new RP ad is posted.  The right click menu will now try to position with "View Profile" under your cursor.<br />05/05 version 14.50.40 The chat textarea now properly shows your set color. Fixed an error upon leaving a room as the last person.<br />05/17 version 14.50.45 Fixed a bug where tabs would not properly switch when leaving a room. You no longer have to refocus a tab to send a message to someone who returned after logging off.<br />05/19 version 14.50.50 Fixed being unable to strip room owner powers by removing co-owners from group.</div>')
				);
			updates.append( $('<p style="cursor:pointer;" class="news">Q3-Q4 2011 patch notes:</p>').append('<div style="font-size:12px;display:none;">06/02 version 15.00.00 Set logs to dump in a window when your browsers storage gets full.  Updated the server and the clients framework that interacts with it for better performance and some bug fixes. All PM notifications now scroll the window.<br /></div>')
				);
			updates.append('<p>Q1-Q2 2012 patch notes:</p><div style="font-size:12px;">01/14 version 15.00.10 Fixed offline messages to others not saving under their proper name. Made these updates display better(toggle open/close). Added a close button to errors.<br /></div>');
			$('.news').children()
			$('.news').toggle(function(ev){
				$(this).children().show();
			}, function(ev){
				$(this).children().hide();
			});
		},
		'scripts': APE.Config.scripts //Scripts to load for APE JSF
	});
	
	var lastNotification;
	var focused = true;
	$(window).bind('blur', function(){ focused = false; })
			.bind('focus', function(){
				focused = true;
				if (lastNotification)
					lastNotification.cancel();
			});
	function desktopNotify(title,body){
		if( !focused ) {
			if( window.webkitNotifications ) {
				if( window.webkitNotifications.checkPermission() == 0 ) { // 0 is PERMISSION_ALLOWED
					var origLen = body.length;
					body = body.substring(0,60);
					if( body.length < origLen )
						body = body + '...';
					if (lastNotification)
						lastNotification.cancel(); //close the old one so there is never more than one.
					lastNotification = webkitNotifications.createNotification('null.png', title, body);
					lastNotification.show();
				}
				else {
					alert('You have\'t set permissions for desktop notifications in settings.');
				}
			}
		}
	}

	var imSound = $("<div />").appendTo("body").jPlayer({ready: function () {
			$(this).jPlayer("setMedia", {mp3: "sounds/imsound.mp3"});
		}});
	var chatSound = $("<div />").appendTo("body").jPlayer({ready: function () {
			$(this).jPlayer("setMedia", {mp3: "sounds/imsound.mp3"});
		}});
	var notifySound = $("<div />").appendTo("body").jPlayer({ready: function () {
			$(this).jPlayer("setMedia", {mp3: "sounds/boop.mp3"});
		}});
	//settings
	var userOptions = {
		color: '000000'
	};
	var accOptions = {
		imVol: 80,
		chatVol: 0,
		notifyVol: 80,
		fontSize: 13,
		maxMsgs: 100,
		notifyPM: false,
		notifyChat: false,
		notifyFriend: false,
		notifies: [],
		disableNotification: false
	};
	var play = {
		imSound: function(){
			imSound.jPlayer("stop").jPlayer("play");
		},
		chatSound: function(){
			chatSound.jPlayer("stop").jPlayer("play");
		},
		notifySound: function(){
			notifySound.jPlayer("stop").jPlayer("play");
		}
	};
	var settings = {
		imVolume: function(restore){
			var $slider = $("#im-vol");
			settings.updateSlider($slider);
			
			var value = $slider.slider("option", "value");
			accOptions.imVol = value;
			chat.cookie.set();
			
			imSound.jPlayer( "volume", parseFloat('0.'+(value - 1)) );
			if( restore != true )
				play.imSound();
		},
		chatVolume: function(restore){
			var $slider = $("#chat-vol");
			settings.updateSlider($slider);
			
			var value = $slider.slider("option", "value");
			accOptions.chatVol = value;
			chat.cookie.set();
			
			chatSound.jPlayer( "volume", parseFloat('0.'+(value - 1)) );
			if( restore != true )
				play.chatSound();
		},
		notifyVolume: function(restore){
			var $slider = $("#notify-vol");
			settings.updateSlider($slider);
			
			var value = $slider.slider("option", "value");
			accOptions.notifyVol = value;
			chat.cookie.set();
			
			notifySound.jPlayer( "volume", parseFloat('0.'+(value - 1)) );
			if( restore != true )
				play.notifySound();
		},
		updateSlider: function($slider){
			if( $slider.slider("option", "value") == 0 )
				$slider.parent().find('input').attr('checked',true);
			else
				$slider.parent().find('input').attr('checked',false);
		},
		setVolumeSliders: function(){
			$("#im-vol, #chat-vol, #notify-vol").slider({
				range: "min",
				max: 100,
				step: 5
			});
			$("#im-vol").slider("option", "value", accOptions.imVol);
			$("#chat-vol").slider("option", "value", accOptions.chatVol);
			$("#notify-vol").slider("option", "value", accOptions.notifyVol);
			$("#im-vol").slider("option", "change", settings.imVolume);
			$("#chat-vol").slider("option", "change", settings.chatVolume);
			$("#notify-vol").slider("option", "change", settings.notifyVolume);
			settings.imVolume(true);
			settings.chatVolume(true);
			settings.notifyVolume(true);
			if( window.webkitNotifications ) {
				if( window.webkitNotifications.checkPermission() != 0 ) {
					$('<a href="">Grant permission for notifications</a>').click(function(ev){
						ev.preventDefault();
						window.webkitNotifications.requestPermission();
					})
					.prependTo('#desktop-notify');
				}
			}
			
			$("#im-vol, #chat-vol, #notify-vol").parent().find('input').change(function(){
				if($(this).is(':checked')){
					var $slider = $(this).parent().parent().find('.ui-slider');
					if( $slider.attr('id') == 'im-vol' )
						accOptions.imVol = 0;
					if( $slider.attr('id') == 'chat-vol' )
						accOptions.chatVol = 0;
					if( $slider.attr('id') == 'chat-vol' )
						accOptions.notifyVol = 0;
						
					chat.cookie.set();
				}
			});
		},
		updateFontSize: function(){
			var value = $("#font-size").val();
			$("#pmChat").css("font-size", value+"px");
			$(".chatBox > div").css("font-size", value+"px");
			
			accOptions.fontSize = value;
			chat.cookie.set();
		},
		loadSettings: function(){
			settings.setVolumeSliders();
			$("#font-size").val(accOptions.fontSize);
			$("#max-msgs").val(accOptions.maxMsgs);
			$("#notifies").val( String(accOptions.notifies) );
			
			if( accOptions.notifyPM ) $("#notify-pm").attr('checked','checked');
			if( accOptions.notifyChat ) $("#notify-chat").attr('checked','checked');
			if( accOptions.notifyFriend ) $("#notify-friend").attr('checked','checked');
			$("#notify-pm").change(function(){ accOptions.notifyPM = $("#notify-pm").attr('checked'); chat.cookie.set(); });
			$("#notify-chat").change(function(){ accOptions.notifyChat = $("#notify-chat").attr('checked'); chat.cookie.set(); });
			$("#notify-friend").change(function(){ accOptions.notifyFriend = $("#notify-friend").attr('checked'); chat.cookie.set(); });
			
			settings.updateFontSize();
			$("#max-msgs").change(function(){
				var val = $("#max-msgs").val();
				if( val == '' )
					val = false;
				
				accOptions.maxMsgs = val;
				chat.cookie.set();
			});
			$("#notifies").change(function(){
				var vals = $("#notifies").val();
				if (vals == '') 
					vals = [];
				else {
					vals = vals.split(',');
					$.each(vals, function(i){
						vals[i] = this.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
					});
				}
				accOptions.notifies = vals;
				chat.cookie.set();
			});
		}
	};
	$("#font-size").change(function(){
		settings.updateFontSize();
	});
	$('.clearchat').bind('click', function(){
		$("#mainChat div div").remove();
	});
	$('.new-pm').click(function(ev){
		ev.stopPropagation();		
		var $el = $('#newPM');
		$el.show();
		$el.position({
				my: "left top",
				at: "left bottom",
				of: $(this),
				collision: "fit"
			});
		$('#newPM .input-button-combo > input').focus();
		var mouse_is_inside = false;
		$el.hover(function(){
				mouse_is_inside = true;
			}, function(){
				mouse_is_inside = false;
			});
		$("body").mouseup(function(){ 
			if( !mouse_is_inside ){
				$el.hide();
				$("body").unbind('mouseup');
			}
		});
	});
	$('#newPM .input-button-combo > input').keydown(function(){
		var username = encodeURIComponent( $('#newPM .input-button-combo > input').val() );
		if( event.keyCode == 13 ){
			chat.pm.create(username);
			$('#newPM').hide();
		}
	});
	$('#newPM .input-button-combo > button').click(function(ev){
		var username = encodeURIComponent( $('#newPM .input-button-combo > input').val() );
		chat.pm.create(username);
		$('#newPM').hide();
	});
chat = {
	user:{
		name: null,
		access: null,
		userid: null,
		accid: null
	},
	
	init: function(core, options){
		chat.currentPipe = null;
		chat.currentPMPipe = null;
		chat.currentPubid = null;
		chat.currentPM = null;
		chat.currentChannel = null;
		chat.selfPubid = null;
		chat.rooms = {};
		chat.RPHusers = {};
		chat.usersByPubid = {};
		chat.userLocation = {};
		chat.buddyList = {};
		chat.buddyList.onlines = {"properties": {"name":"Online Friends", "nusers":0, "users":[]}};
		chat.buddyList.groupies = {"properties": {"name":"Online Group Members", "nusers":0, "users":[]}};
		chat.buddyList.offlines = {"properties": {"name":"Friends", "nusers":0, "users":[]}};
		chat.buddyList.ignores = {"properties": {"name":"Blocked", "nusers":0, "users":[]}};
		chat.ISs = {};
		chat.buttons.initAll();
		
		chat.createListHeader(chat.buddyList.onlines);
		chat.createListHeader(chat.buddyList.groupies);
		chat.createListHeader(chat.buddyList.offlines);
		chat.createListHeader(chat.buddyList.ignores);
		
		client.addEvent('load', this.login.prompt);
		//client.addEvent('ready', this.setup); // basic chat stuff on start.		
		client.addEvent('uniPipeCreate', this.newUniPipe);
		client.addEvent('multiPipeCreate', function(pipe, options){
			if (pipe.name.charAt(0) != '*')	chat.createChannel(pipe, options);
		});
		//client.addEvent('uniPipeDelete', this.closePM);
		client.addEvent('multiPipeDelete', this.leaveChannel);
		client.addEvent('userJoin', this.roomJoin);
		client.onRaw('gjoin', function(raw)	{
			var roomname = raw.data.roomname;
			var username = raw.data.name;
			if (!chat.rooms[roomname]) {
				chat.rooms[roomname] = {'ops':[], 'owners':[],"type":"room", "properties": {"name":roomname, "nusers":0, "users":[]}};
			}
			var room = chat.rooms[roomname];

			if(raw.data.access) {
				if(raw.data.access == "1")
					room.owners.push(username);
				else if(raw.data.access == "2")
					room.ops.push(username)
			}
			chat.userLocation[username] = roomname;
			chat.globalJoin(username, room);
		});
		client.onRaw('gleft', function(raw)	{
			var roomname = raw.data.room;
			var username = raw.data.name;
			
			var room = chat.rooms[roomname];
			if(room){
				chat.globalLeave(username, room);
				chat.userLocation[username] = null;
			}
		});
		client.onRaw('roomlist', function(raw)	{
			$.each(raw.data.users, function() {
				var roomname = this.roomname;
				var username = this.name;
				if (!chat.rooms[roomname]) {
			 		chat.rooms[roomname] = {'ops':[], 'owners':[], "type":"room", "properties": {"name":roomname, "nusers":0, "users":[]}};
				}
				var room = chat.rooms[roomname];
				
				if(this.access) {
					if(this.access == "1")
						room.owners.push(username);
					else if(this.access == "2")
						room.ops.push(username);
				}
				
				chat.userLocation[username] = roomname;
				chat.globalJoin(username, room);
		    });
		});
		client.onRaw('userlist', function(raw)	{
			$.each(raw.data.users, function() {
				var nraw = {"data":{"casttype":"uni", "pubid":this.pubid,"properties":{"name":this.properties.name, "status":this.properties.status, "hex":this.properties.hex}}};
				chat.setOnline(nraw);
		    });
		});
		client.onRaw('deleteroom', function(raw){
			var roomname = raw.data.name;
			var room = chat.getRoomByName(roomname);
			if(chat.currentChannel){
				if( roomname != chat.currentChannel.properties.name ){
					$.each(room.properties.users,function(){
						var username = this;
						chat.globalLeave(username, room);
						chat.userLocation[username] = null;
					});
				}
			}
			else {
				$.each(room.properties.users,function(){
					var username = this;
					chat.globalLeave(username, room);
					chat.userLocation[username] = null;
				});
			}
		});
		client.onRaw('kicked', function(raw, pipe){ chat.kickMsg(raw.data, raw.data.from, pipe); } );
		client.onRaw('banned', function(raw, pipe){ chat.banMsg(raw.data, raw.data.from, pipe); } );
		client.onRaw('updateaccess', chat.updateAccess);
		client.onRaw('newstatus', chat.updateStatus);
		client.onRaw('newcolor', chat.updateColor);
		client.onRaw('roomoptions', chat.updateRoom);
		client.onRaw('signout', chat.setOffline);
		client.onRaw('signin', chat.setOnline);
		client.onRaw('typingstart', chat.msg.typing.start);
		client.onRaw('typingstop', chat.msg.typing.stop);
		client.onRaw('addrequest', chat.buttons.buddyList.receive_add_request);
		client.onRaw('addaccept', chat.buttons.buddyList.add_accepted);
		client.onRaw('adddeny', chat.buttons.buddyList.add_denied);
		client.onRaw('addrequesterror', chat.buttons.buddyList.errors);
		client.onRaw('sharerequest', chat.imageshare.receive_request);
		client.onRaw('sharestart', chat.imageshare.start);
		client.onRaw('sharedeny', chat.imageshare.denied);
		client.onRaw('sharecurview', chat.imageshare.others_current_img);
		client.onRaw('shareaddimg', chat.imageshare.receive_img);
		client.onRaw('shareremoveimg', chat.imageshare.receive_delete);
		client.onRaw('sharestop', chat.imageshare.receive_end);
		client.onRaw('massmessage', chat.massMessage);
		client.onRaw('newtopic', chat.msg.alert);
		client.onRaw('idlestart', chat.msg.idle.start);
		client.onRaw('idleend', chat.msg.idle.stop);
		client.onRaw('idletime', chat.msg.idle.time);
		client.addEvent('userLeft', chat.roomLeave);
		client.addEvent('restoreEnd',chat.restoreEnd);
		client.onCmd('send', chat.msg.cmdSend);
		client.onRaw('data', chat.msg.rawData);
		client.onRaw('clist', chat.channels.addChannels);
		client.onRaw('alist', chat.lfrp.addAdverts);
		client.onRaw('newadvert', chat.lfrp.newAdvert);
		client.onRaw('banlist', chat.populateBans);
		client.onRaw('err', chat.errorHandler);
		client.onRaw('login', chat.setup);
		client.onRaw('ident', function(raw){ chat.selfPubid = raw.data.user.pubid});
		//client.addEvent('apeDisconnect', chat.disconnected);
		
		/*if(!chat.user.name && !core.options.restore){
			chat.login.prompt();
		} else {
			core.start({'name':chat.user.name});
			core.start(chat.user.name);
		}*/
	},
	
	login: {
			prompt: function(error){
				$("#loginDialog").dialog({
					bgiframe: true, autoOpen: true, height: 280, modal: true,
					open: function(event, ui) {
						$("div#loginDialog .innerbg").css("height", $("div#loginDialog").height() - $("div#loginDialog .ui-dialog-buttonpane").height() - 5);
					},
					resize: function(event, ui) {
						$("div#loginDialog .innerbg").css("height", $("div#loginDialog").height() - $("div#loginDialog .ui-dialog-buttonpane").height() - 5);
					},
					buttons: {
						'Login': function(ev) {
							$(this).find('button').attr('disabled', true);
							$("#loginDialog form").submit();
						},
						'Register': function(ev) {
							ev.preventDefault();
							window.open('http://www.rphaven.com/register.php');
						}
					}
				});
				$("#loginDialog form").submit(function(ev){
					if( $(this).hasClass('disabled') )
						return false;
					ev.preventDefault();
					chat.login.postAjax($(this));
				});

			},
			
			postAjax: function($this){
				$this.addClass('disabled');
				$.ajax({
					type: "POST", url: 'ajax_chat.php?login', dataType: 'json', 
					data: "username=" + $("#username").val() + "&password=" + hex_md5($("#password").val()),
					success: function(json) {
						if (json.error == true) {
							$this.removeClass('disabled');
							$("#loginDialog div.ui-state-highlight").removeClass("ui-state-highlight").addClass("ui-state-error");
					 		$("#loginDialog").find("p").replaceWith('<p class="ui-state-error ui-corner-all" style="padding: 1em .7em;"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span><strong>Error:</strong>' + json.msg + '</p>');
						} else {
							$("#loginDialog").find("p").replaceWith('<p style="padding: 1em 0.7em;" class="ui-state-highlight ui-corner-all"><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-info"></span> Logging in...</p>');
							chat.user.name = encodeURIComponent(json.msg);
		 					chat.user.access = json.access;
							chat.user.userid = json.userid;
							chat.user.accid = json.accid;
							userOptions.color = '000000';
							chat.cookie.get();
							settings.loadSettings();
							
							if(json.access == 3){
								chat.make_admin_toolbar();
							}
							if(json.buddies)
								$.each(json.buddies, function() {
									var username = encodeURIComponent(String(this));
									chat.buddyList.offlines.properties.users.push(username);
									chat.populateOfflines(username);
								});
							if(json.ignores)
								$.each(json.ignores, function() {
									var username = encodeURIComponent(String(this));
									chat.buddyList.ignores.properties.users.push(username);									
									chat.buttons.populateIgnores(username);
								});
							if(json.groups)
								$.each(json.groups, function() {
									var groupname = this.name;
									if (chat.buddyList[groupname] == null) {
								 		chat.buddyList[groupname] = {"type":"group","properties": {"name":groupname, "nusers":0, "users":[]}};
									}
									var group = chat.buddyList[groupname];
									$.each(this.users, function() {
										var username = encodeURIComponent(String(this));
										group.properties.users.push(username);
										
										chat.populateGroups(username, group);
									});
								});
							var sendLogin = function(){
								core.start({'name':json.msg,
											'password':hex_md5($("#password").val()),
											'version':150000,
											'color':userOptions.color});
								$this.removeClass('disabled');
							};
							setTimeout(sendLogin,1500);
							chat.buttons.colorPicker.hexToSliders(userOptions.color);
							chat.buttons.topBar.setName();
							chat.buttons.topBar.setUserCount( 0 );
						}
					}
				});
			},
			
			nickUsed: function(){
				$("#loginDialog").find("p").replaceWith('<p class="ui-state-error ui-corner-all" style="padding: 1em .7em;"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span><strong>Error:</strong>Name is in use.  It\'s either still logged on, or hasn\'t been timed-out yet.  For the latter, wait 30 seconds and try again.</p>');
			}
	},
	
	setup: function(type, pipe, options){
		$("#loginDialog").dialog('close');
		$("textarea[name=chatInput]")
			.keydown(function(event){
				if (event.keyCode == 13)
					event.preventDefault();
				if (event.keyCode == 13 && event.ctrlKey == false && $(this).val() != '') {
					if(chat.currentPipe != null) {
						var newMessage = $(this).val();
						var pipe = chat.getCurrentPipe();
						pipe.send(newMessage);
						$(this).val('');
						chat.msg.writeLog(pipe.properties.name, newMessage, 'multi');
					}
					else{
						$("#mainChat").append('<div class="subAlert">You are not in a room, so you can\'t talk.</div>');
					}
				}
				else if (event.keyCode == 13 && event.ctrlKey == true && $(this).val() != '') {
					$(this).val( $(this).val() + '\n' );
				}
			});
			
		$('textarea.expand').TextAreaExpander({
			onResize: function(){
		  		resizeCHATtextdiv();
				chat.scrollMsg($("#mainChat"), true);
			}
		});
		
		$.idleTimer(600000);
		
		$(document).bind("idle.idleTimer", function(){
			core.request.send('SENDIDLE', {"pubid":core.user.pubid});
		});
		$(document).bind("active.idleTimer", function(){
			core.request.send('SENDIDLEEND', {"pubid":core.user.pubid});
		});
		
		$.ajax({
			type: "POST", url: 'ajax_chat.php?get_offline_msgs', dataType: 'json', 
			data: "userid=" + chat.user.userid,
			success: function(json){
				if(!json.error){
					$.each(json, function(i, user){
						var PM = chat.pm.create( encodeURIComponent(user.name) );
						if(window.console) console.log(PM);
						//var PM = chat.pm.getByName(user.name);
						$('<p class="ui-state-highlight ui-corner-all" style="padding: 0.5em;"><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>You\'ve received messages while offline, they are listed below.</p>')
							.appendTo(PM.container);
						$.each(user.msgs, function(i, msg){
							$("<p style='color:#777'><span class='dull'>" + makeTimestamp(msg.date) + "</span><b>" + user.name + ":</b> " + chat.msg.parseMessage(msg.msg, 'uni') + "</p>")
								.appendTo(PM.container);
							chat.scrollMsg(PM.container.parent());
							chat.logs.addMsg(encodeURIComponent(user.name), msg.msg, 'other', msg.date);
						});
					});
				}
			}
		});
		
		chat.channels.init();
		chat.channels.openRoomlist();
	},
	
/* Functions used by commands. */
	setPipeName: function(pipe, options){
		if(options.name){
			pipe.name = options.name;
			return;
		}
		if(options.from){
			pipe.name = options.from.properties.name;
		} else {
			pipe.name = options.pipe.properties.name;
		}
	},
	
	isSelf: function(pubid){
		if(pubid == chat.selfPubid)
			return true;
		else
			return false;
	},
	
	getCurrentPipe: function(){
		return chat.currentPipe;
	},
	
	getCurrentPMPipe: function(){
		return chat.currentPMPipe;
	},
	
	notify: function(PM){
		PM.tab.addClass('newMessage');
		PM.tab.animate({ opacity: 0.30 }, 350 ).animate({ opacity: 0.90 }, 350 ).animate({ opacity: 0.50 }, 350 ).animate({ opacity: 0.90 }, 350 ).animate({ opacity: 0.70 }, 350 ).animate({ opacity: 0.95 }, 350 ).animate({ opacity: 0.80 }, 425 ).animate({ opacity: 1.0 }, 500 );
	},
	
	scrollMsg: function(target, force){
		if( target[0] ){
			var lastHeight = target.children(':visible').children(':last').outerHeight();
			if(target.scrollTop() > target[0].scrollHeight - target.height() - lastHeight - 30) {
				var scrollSize = target[0].scrollHeight;
				target.scrollTop(scrollSize);
			}
			if(force)
			{
				var scrollSize = target[0].scrollHeight;
				target.scrollTop(scrollSize);
			}
		}
	},
	
	newUniPipe: function(pipe, options){
		chat.setPipeName(pipe, options);
		var pubid = pipe.pipe.pubid;
		var user = core.getPipe(pubid);
		
		chat.pm.create(user.properties.name);
	},
	
	getRoomByName: function(name){
		var room = chat.rooms[name];
		
		if(room)
			return room;
		else
			return false;
	},
	
	getUserByName: function(name){
		var user = null;
		user = chat.RPHusers[name];
		
		if( !user ){
			$.each(chat.RPHusers, function(i, val){
				if( this.properties.name.toLowerCase() == name.toLowerCase() ){
					user = this;
					return false;
				}
			});
			
			if( !user ){
				chat.createUser(name);
				user = chat.RPHusers[name];
			}
		}
		
		return user;
	},
	getUserByPubid: function(pubid){
		var username = chat.usersByPubid[pubid];
		user = chat.RPHusers[username];
		
		if( !user ){
			chat.createUser(name);
			user = chat.RPHusers[name];
		}
		
		return user;
	},
	
	setCurrentPMPipe: function(username, save){
		save = !save;
		var user = chat.getUserByName(username);
		if(chat.currentPM){
		 	$(chat.currentPM.tab).removeClass('newMessage active ui-state-focus');
			$(chat.currentPM.container).hide();
			$(chat.currentPM.input).hide();
			$(chat.currentPM.topButtons).hide();
		}
		if( user.pubid ){
			chat.currentPMPipe = core.getPipe(user.pubid);
			if( chat.currentPMPipe == null ){
				user.pipe = {pubid:user.pubid, properties:user.properties};
				chat.currentPMPipe = core.newPipe('uni', user);
			}
		}
		else
			chat.currentPMPipe = null;
		
		chat.currentPM = chat.pm.getByName(username);
		
		if( !isMobile )
			$("#pmDialog").dialog('option', 'title', 'Conversing with ' + $(chat.currentPM.tab).find('a').html());
		chat.currentPM.tab.addClass('active ui-state-focus');
		chat.currentPM.container.show();
		$(chat.currentPM.input).show();
		chat.currentPM.topButtons.show();
		chat.scrollMsg(chat.currentPM.container.parent(), true);
		resizePMtextdiv();
		//if(save) core.setSession('currentPipe',chat.currentPipe.getPubid());
		return chat.currentPMPipe;
	},
	setCurrentPipe: function(pubid, save){
		save = !save;
		if(chat.currentChannel){
			if(chat.currentChannel.els)
				$(chat.currentChannel.els.userlist).hide();
		}
		if(chat.currentPipe){
			var room = chat.getRoomByName(chat.currentPipe.properties.name);
		 	room.tab.removeClass('newMessage active typing ui-state-focus');
			room.container.hide();
			room.input.hide();
		}
		
		chat.currentPubid = pubid;
		chat.currentPipe = core.getPipe(pubid);
		var roomname = chat.currentPipe.properties.name;
		chat.currentChannel = chat.rooms[roomname];
		
		chat.currentChannel.els.userlist.show();
		
		var room = chat.getRoomByName(roomname);
		room.tab.addClass('active ui-state-focus');
		room.container.show();
		room.input.show();
		chat.scrollMsg(room.container.parent(), true);
		resizeCHATtextdiv();
		
		//scrolluserlist
		var position = room.els.room.position().top;
		var offset = room.els.room.parent().position().top;
		position = position - offset;
		var cur = room.els.room.parent().scrollTop();
		room.els.room.parent().parent().scrollTop(position + cur);
		//if (save)
			//core.setSession({'currentPipe':this.currentPipe.getPubid()});
		return chat.currentPipe;
	},
	
	createChannel: function(pipe, options){		
		chat.channels.closeRoomlist();
		
		var roomname = pipe.name;
		var room = {};
		if (chat.rooms[roomname] == null) {
	 		chat.rooms[roomname] = {"owners":[],"ops":[],"type":"room","properties": {"name":roomname, "nusers":0, "users":[]}};
			room = chat.getRoomByName(roomname);
		
			chat.createListHeader(room);
			room.els.room.children('.headText').show();
		}
		room = chat.getRoomByName(roomname);
		room.container = $('<div />').html('<p>&nbsp;</p>').hide().appendTo('#mainChat');
		room.tab = $('<div class="chatTab ui-corner-all" />').appendTo('#chatTabs');
		
		if (room.properties.topic) {
			$('<div><div class="first">[' + makeTimestamp() + ']<span>*</span></div><div>Topic for ' + decodeURIComponent(pipe.name) + ': ' + decodeURIComponent(room.properties.topic) + '</div></div>')
				.appendTo(room.container);
		}
		if( room.properties.groupid ){
			$('<div><div class="first">[' + makeTimestamp() + ']<span>*</span></div><div><a href="http://www.rphaven.com/group.php?id=' + room.properties.groupid + '" target="_blank">Group page</a></div></div>')
				.appendTo(room.container);
		}
				
		$('<a href="#" />')
			.text(decodeURIComponent(roomname))
			.click(function(event){
				event.preventDefault();
				chat.setCurrentPipe(pipe.getPubid());
			})
			.appendTo(room.tab);
		room.close = $('<span class="ui-corner-all" title="close"><a class="ui-icon ui-icon-closethick">close</a></span>')
			.appendTo(room.tab);
		room.close.bind("click", function(){
			if( room.close.css('opacity') == 1 ){
				var leavepipe = core.getPipe(pipe.getPubid());
				leavepipe.left();
			}
		});
		room.tab.hover(function(){
				room.close.css('opacity', '1.0');
			},function(){
				room.close.css('opacity', '0.1');
			});
		room.input = $('<textarea name="chatInput" style="color:#'+userOptions.color+'" />').hide()
			.keydown(function(ev){
				//submit on enter, unless pressing Ctrl
				if (ev.keyCode == 13)
					ev.preventDefault();
				if (ev.keyCode == 13 && ev.ctrlKey == false && $(this).val() != '') {
					var newMessage = $(this).val();
					//var pipe = chat.getCurrentPipe();
					pipe.send(newMessage);
					$(this).val('');
					chat.msg.writeLog(pipe.properties.name, newMessage, 'multi');
				}
				else if (ev.keyCode == 13 && ev.ctrlKey == true && $(this).val() != '') {
					$(this).val( $(this).val() + '\n' );
				}
			})
			.appendTo('#not-mainChat .textarea');
		room.input.TextAreaExpander({
			onResize : function() {
  				resizeCHATtextdiv();
				chat.scrollMsg(room.container.parent(), true);
			}
		});
		
		chat.setCurrentPipe(pipe.getPubid());
	},
	
	leaveChannel: function(pipe){
		var roomname = pipe.properties.name;
		var room = chat.getRoomByName(roomname);
		/*$("<div><div class='first'>[" + makeTimestamp() + "]<span>*</span></div><div>You have left " + decodeURIComponent(pipe.name) + "</div></div>")
			.appendTo(room.container);*/
		room.tab.remove();
		room.container.remove();
		room.input.remove();
		delete room.tab;
		delete room.container;
		delete room.input;
		
		if(room.properties.nusers <= 0)	{
			delete chat.rooms[room.properties.name];
		}
		
		chat.currentPubid = null;
		chat.currentChannel = null;
		chat.currentPipe = null;
		chat.currentPubid = null;
		
		$('#chatTabs').children('div').each(function(){
			$(this).find("a").click();
			return false;
		});
	},
	
	createListHeader: function(room){
		if( room.type == "room" )
			var appendee = "#userlist > ul";
		else
			var appendee = "#buddylist > ul";
		room.els = {};
		var roomname = room.properties.name;
		room.els.room = $('<li class="headItem" />')
			.html(
				$('<span class="headText emboss-lgrey"><a>' + roomname + '</a></span>')
				.find("a").prepend(
					room.els.usercount = $('<span>0-</span>')
				).end()
				.add(
					room.els.userlist = $('<ul class="userListContainer" id="'+ roomname +'" />').hide()
				)
			).appendTo(appendee);
		
		room.els.info = {};
		room.els.info.body = $('<li class="room-info"><span class="clear">**</span></li>');
		room.els.info.body.prependTo(room.els.userlist);
		if( room.type == "room" ){
			room.els.info.joinBtn = $('<button>Join Room</button>').button()
				.appendTo(room.els.info.body);
			room.els.info.joinBtn.click(function(e){
				core.join(roomname);
			});
		}
			
		$(room.els.room)
			.toggle(function(event){
				if( !$(event.target).closest('ul').hasClass('userListContainer') ) {
					room.els.userlist.show();
				}
			}, function (event) {
	      		if( !$(event.target).closest('ul').hasClass('userListContainer') ){
					room.els.userlist.hide();
			}
	      }
		);
	},
	
	getBuddyUser: function(username){
		var user = chat.buddyList.offlines.properties.users[username];		
		return user;
	},
	
	createUser: function(username, options){
		if( !chat.RPHusers[username] ){
			var status = "none";
			var color = "000000";
			var pubid = '';
			var online = false;
			if(options){
				if(options.status)
					status = options.status;
				if(options.color)
					color = options.color;
				if(options.pubid)
					pubid = options.pubid;
				if(options.online)
					online = true;
			}
			chat.RPHusers[username] = {"casttype":"uni","online":online,"pubid":pubid,"els":{"live":[]}, properties:{"name":username,"status":status,"hex":color}};
			var user = chat.getUserByName(username);
			//basic element to be updated in lists
			user.els.base = $('<li style="color:#' + user.properties.hex + ';" />').text(decodeURIComponent(user.properties.name));			
			user.els.base.bind("click", function(e){
					chat.dropdown.action(user, "Open PM");
			  	}).rightClick(function(e){
					chat.dropdown.createDropdown(e, user);
			 	})
				.append(
						user.els.status = $('<span class="user-status" />').html('&nbsp')
					);
			
			//sexy donator hover el.*/			
			var hoverEl = function(user){
				user.els.base.mouseenter(function(e){
					var $this = $(this);
					var offset = $this.offset();
					var width = $this.width();
					var flip = false;
					if (offset.left > ($("body").width() / 3))
						flip = true;
					var el = $('<div class="userlist-hover" style="color:#' + user.properties.hex + ';" />').text($(this).text());
					el.css({
						'width': width,
						'left': offset.left,
						'top': (offset.top - 3)
					});
					el.appendTo("body");
					
					var mypos = 'left';
					var atpos = 'right';
					if (flip) {
						mypos = 'right';
						atpos = 'left';
					}
					var el2 = $('<div class="userlist-hover2" />');
					var content = $('<div />').appendTo(el2);
					var img = $('<img src="test" />').appendTo(content);
					el2.appendTo("body");
					el2.position({
						of: el, my: mypos, at: atpos, collision: 'fit'
					});
					var el2Shadow = $('<div class="userlist-hover2-undershadow" />');
					el2Shadow.appendTo("body");
					el2Shadow.position({
						of: el, my: mypos, at: atpos, collision: 'fit'
					});
					
					el.addClass(user.properties.name);
					el2.addClass(user.properties.name);
					el.mouseleave(function(e){
						var eclass = $(e.relatedTarget).attr('class');
						if( eclass != ('userlist-hover ' + user.properties.name) && eclass != ('userlist-hover2 ' + user.properties.name) ) {
							el.remove();
							el2.remove();
							el2Shadow.remove();
							console.log('el remove' + user.properties.name);
						}
					});
					el2.mouseleave(function(e){
						var eclass = $(e.relatedTarget).attr('class');
						if( eclass != ('userlist-hover ' + user.properties.name) && eclass != ('userlist-hover2 ' + user.properties.name) ) {
							el.remove();
							el2.remove();
							el2Shadow.remove();
							console.log('el2 remove' + user.properties.name);
						}
					});
					
					$("<p />").text('woosh').appendTo(content);
					$("<p />").text('woosh').appendTo(content);
					$("<p />").text('woosh').appendTo(content);
				});
			};
			//hoverEl(user);
			//end donator hover el
			if(user.properties.status != 'none') {
				user.els.status.text('(' + decodeURIComponent(user.properties.status) + ')');
				user.els.base.attr('title', decodeURIComponent(user.properties.status));
			}
			//end element
			
			chat.dropdown.addOption(user, ["View Profile","Block"]);
		}
		if(options){
			var user = chat.getUserByName(username);
			var status = "none";
			var color = "000000";
			var online = false;
			if(options.status)
				user.properties.status = options.status;
			if(options.color)
				user.properties.hex = options.color;
			if(options.pubid)
				user.pubid = options.pubid
			if(options.online)
				user.online = true;
			
			if( user.properties.status != 'none' ) {
				user.els.status.text('(' + decodeURIComponent(user.properties.status) + ')');
				user.els.base.attr('title', decodeURIComponent(user.properties.status));
			}
			user.els.base.css('color', '#'+user.properties.hex);
			
			chat.updateUserEls(username);
		}
	},
	
	updateUserEls: function(username){
		var user = chat.getUserByName(username);
		$.each(user.els.live, function(index, el){
			this.css('color', '#'+user.properties.hex);
			if( user.properties.status != 'none' ){
				this.find('.user-status').text("("+ decodeURIComponent(user.properties.status) +")");
				this.attr('title', decodeURIComponent(user.properties.status));
			}
			else {
				this.find('.user-status').html('&nbsp');
				this.attr('title', '');
			}
			//this.html( $(user.els.base.wrap('<div />').parent().html()) );
		});
	},
	
	appendUserEl: function(username, target){
		var user = chat.getUserByName(username);
		var el = user.els.base.clone(true).appendTo(target);
		var roomname = el.parent().attr('id');
		user.els.live.push(el);
		$(target).children('li').each(function(){
			if ($(this).text() > decodeURIComponent(username)) {
				if( $(this).text() == el.text()){
					return false;
				}
				return !el.insertBefore(this);
			}
		});
		return el;
	},
	
	removeUserEl: function(username, target){
		var user = chat.getUserByName(username);
		//search array for the matching element in the target and remove it.
		$.each(user.els.live, function(index, el){
			if( $(this).parent().attr('id') == $(target).attr('id') ){
				this.remove();
				user.els.live.arrayRemove(index);
			}
		});
	},
	
	setOnline: function(raw){
		var userdata = raw.data;
		var username = userdata.properties.name;
		
		chat.createUser(username, {"color":userdata.properties.hex,"status":userdata.properties.status,"pubid":userdata.pubid,"online":true});
		chat.usersByPubid[userdata.pubid] = username;
		
		var user = chat.getUserByName(username);
		var onlines = chat.buddyList.onlines;
		var offlines = chat.buddyList.offlines;
		var groupies = chat.buddyList.groupies;
		chat.dropdown.addOption(user, ["Open PM"]);
		
		if( user.pm ){
			user.pipe = {pubid:user.pubid, properties:user.properties};
			var pipe = core.newPipe('uni', user);			
			var PM = user.pm;
			PM.tab.removeClass('offline');
			
			var msg = decodeURIComponent(username) + " has logged back on at "+makeTimestamp();
			chat.msg.appendSysMsg(user.properties.name, msg);
			
			chat.pm.update(username);
		}
		
		//check for name in offline friends list.
		if( $.inArray(username, offlines.properties.users) != -1 ){
			onlines.properties.nusers+=1;
			onlines.properties.users.push(username);
			
			onlines.els.usercount.text(onlines.properties.nusers + '-');
			chat.appendUserEl(username, onlines.els.userlist);
			if( onlines.properties.nusers == 1 )
				onlines.els.userlist.show();
			
			if( accOptions.notifyFriend )
				desktopNotify(decodeURIComponent(username), 'has logged on.');
		}
		var inGroup = false;
		var group = '';
		//check for name in group lists.
		$.each(chat.buddyList, function(id, arr){
			if(arr.properties.name != "Blocked" && arr.properties.name != "Friends" && arr.properties.name != "Online Friends" && arr.properties.name != "Online Friend Members"){
				if( $.inArray(username, arr.properties.users) != -1 ){
					inGroup = true;
					group = arr;
					return false;
				}
			}
		});
		if( inGroup ){
			groupies.properties.nusers+=1;
			groupies.properties.users.push(username);
			
			groupies.els.usercount.text(groupies.properties.nusers + '-');
			chat.appendUserEl(username, groupies.els.userlist);
			
			if( groupies.properties.nusers == 1 )
				groupies.els.userlist.show();
			
			if( accOptions.notifyFriend )
				desktopNotify(decodeURIComponent(username), 'has logged on.');
		}
		chat.buttons.topBar.updateUserCount('up');
	},
	
	setOffline: function(raw){
		var userdata = raw.data;
		var username = userdata.properties.name;
		var user = chat.getUserByName(username);
		var onlines = chat.buddyList.onlines;
		var groupies = chat.buddyList.groupies;
		
		delete chat.usersByPubid[userdata.properties.pubid];
		
		user.online = false;
		
		if(core.pipes.has(user.pubid)){
			var PM = user.pm;
			
			var msg = decodeURIComponent(username) + " has logged off at "+makeTimestamp()+".<br />They'll receive further messages that you send when they return.";
			chat.msg.appendSysMsg(user.properties.name, msg);
			
			chat.pm.update(username);
		}
		
		if( $.inArray(username, onlines.properties.users) != -1 ){
			onlines.properties.nusers-=1;
			onlines.els.usercount.text(onlines.properties.nusers + '-');
			
			chat.removeUserEl(username, onlines.els.userlist);
			if( onlines.properties.nusers == 0 )
				onlines.els.userlist.hide();
		}
		if( $.inArray(username, groupies.properties.users) != -1 ){
			groupies.properties.nusers-=1;
			groupies.els.usercount.text(groupies.properties.nusers + '-');
			
			chat.removeUserEl(username, groupies.els.userlist);
			if( groupies.properties.nusers == 0 )
				groupies.els.userlist.hide();
		}
		chat.buttons.topBar.updateUserCount('down');
	},
	
	populateOfflines: function(username){
		chat.createUser(username);
		var user = chat.getUserByName(username);
		var list = chat.buddyList.offlines;
		chat.buddyList.offlines.properties.nusers+=1;
		list.els.usercount.text(list.properties.nusers + '-');
		
		chat.dropdown.addOption(user, ["Unfriend"]);
		chat.appendUserEl(username, list.els.userlist);
	},
	
	populateGroups: function(username, group){
		chat.createUser(username);
		var user = chat.getUserByName(username);
		if( group.els == null )
			chat.createListHeader(group);
		
		group.properties.nusers+=1;
		group.els.usercount.text(group.properties.nusers + '-');
		
		chat.appendUserEl(username, group.els.userlist);
	},
	
	roomJoin: function(user, pipe){
		var roomname = pipe.properties.name;
		var room = chat.getRoomByName(roomname);
		var username = user.properties.name;
		var user = chat.getUserByName(username);
		
		var $last = room.container.children(':last');
		if( $last.hasClass('joins') ){
			var el = $("<span>, <span class='clickable' style='color:#"+user.properties.hex+"' title='["+makeTimestamp()+"]'>"+decodeURIComponent(username)+"</span></span>")
				.appendTo( $last.find('.users') );
			el.find('.clickable').rightClick(function(ev) {
					chat.dropdown.createDropdown(ev, chat.getUserByName(username), roomname);
				}).bind("click", function(e){
					if( e.target == this )
						chat.dropdown.action(user, "Open PM");
				});
			$last.find('.msg').text( 'have joined '+decodeURIComponent(pipe.name) );
		}
		else{
			var $html = $("<div class='joins'><div class='first'><img src='bullet_green.png' /></div><div><span class='users' /> <span class='msg'>has joined "+decodeURIComponent(pipe.name)+"</span></div></div>")
				.appendTo(room.container);
			$("<span><span class='clickable' style='color:#"+user.properties.hex+"' title='["+makeTimestamp()+"]'>" + decodeURIComponent(username) + "</span></span>").find('.clickable').rightClick(function(ev) {
					chat.dropdown.createDropdown(ev, chat.getUserByName(username), roomname);
				}).bind("click", function(e){
					if( e.target == this )
						chat.dropdown.action(user, "Open PM");
				})
				.appendTo( $html.find('.users') );
		}
			
		chat.scrollMsg(room.container.parent());
	},
	
	roomLeave: function(user, pipe){
		var roomname = pipe.properties.name;
		var room = chat.getRoomByName(roomname);
		var username = user.properties.name;
		var user = chat.getUserByName(user.properties.name);
		if(room){
			var $last = room.container.children(':last');
			if( $last.hasClass('leaves') ){
				var el = $("<span>, <span class='clickable' style='color:#"+user.properties.hex+"' title='["+makeTimestamp()+"]'>"+decodeURIComponent(username)+"</span></span>")
					.appendTo( $last.find('.users') );
				el.find('.clickable').rightClick(function(ev) {
						chat.dropdown.createDropdown(ev, chat.getUserByName(username), roomname);
					}).bind("click", function(e){
						if( e.target == this )
							chat.dropdown.action(user, "Open PM");
					});
				$last.find('.msg').text( 'have left '+decodeURIComponent(pipe.name) );
			}
			else{
				var $html = $("<div class='leaves'><div class='first'><img src='bullet_red.png' /></div><div><span class='users' /> <span class='msg'>has left "+decodeURIComponent(pipe.name)+"</span></div></div>")
					.appendTo(room.container);
				$("<span><span class='clickable' style='color:#"+user.properties.hex+"' title='["+makeTimestamp()+"]'>" + decodeURIComponent(username) + "</span></span>").find('.clickable').rightClick(function(ev) {
						chat.dropdown.createDropdown(ev, chat.getUserByName(username), roomname);
					}).bind("click", function(e){
						if( e.target == this )
							chat.dropdown.action(user, "Open PM");
					})
					.appendTo( $html.find('.users') );
			}
			
			chat.scrollMsg(room.container.parent());
		}
	},
	
	globalJoin: function(username, room){
		if (room.els == null)
			chat.createListHeader(room);
		
		//in case you're in the hidden room being shown..
		if ( $.inArray(username, room.properties.users) == -1 ){
			var user = chat.getUserByName(username);
			room.properties.users.push(String(username));
			room.properties.nusers+=1;
			room.els.usercount.text(room.properties.nusers + '-');
			
			chat.appendUserEl(user.properties.name, room.els.userlist);
			
			chat.setRoomAccess(user.properties.name, room);
			if(user.properties.name == chat.user.name)
				chat.setRoomOptions(user.properties.name, room);
		}
	},
	
	globalLeave: function(username, room){
		var user = chat.getUserByName(username);
		room.properties.nusers-=1;
		
		if( user )
			chat.removeUserEl(user.properties.name, room.els.userlist);
			
		var arrPos = $.inArray(username, room.properties.users);
		room.properties.users.arrayRemove(arrPos);
		
		if(room.properties.nusers <= 0)	{
			room.els.room.remove();
			delete room.els;
			//delete chat.rooms[room.properties.name];
		}
		else
			room.els.usercount.text(room.properties.nusers + '-');
	},
	
	setRoomAccess: function(username, room){
		var user = chat.getUserByName(username);
		$.each(user.els.live, function(index, el){
		    var roomname = $(this).parent().attr('id');
		    var eachRoom = chat.getRoomByName(roomname);
			el.removeClass('owner op');
			el.find('.owner, .op').remove();
		    if(eachRoom){
				if( chat.isRoomOp(eachRoom, username) ){
					$('<span class="op" title="Room Operator">').prependTo( el );
					el.addClass('op');
				}
				else if( chat.isRoomOwner(eachRoom, username) ){
					$('<span class="owner" title="Room creator/owner">').prependTo( el );
					el.addClass('owner');
				}
		    }
		});
		
		chat.updateUserEls(username);
	},
	
	setRoomOptions: function(username, room){
		var user = chat.getUserByName(username);
		if( chat.isRoomOp(room, username) || chat.isRoomOwner(room, username) & !room.els.opsButton ){
			$target = room.els.room.find('.headText');
			if( !room.els.opsButton ) {
				room.els.opsButton = $('<button style="float:right;">Manage</button>').button().prependTo($target);
				room.els.opsButton.click(function(ev){
					chat.openRoomOptions(room.properties.name);
					ev.stopPropagation();
				});
			}
		}
	},
	
	updateStatus: function(raw){
		var user = chat.getUserByName(raw.data.name);
		user.properties.status = raw.data.status;
		if( user.properties.status != 'none' ) {
			user.els.status.text('(' + decodeURIComponent(user.properties.status) + ')');
			user.els.base.attr('title', decodeURIComponent(user.properties.status));
		}
		else {
			user.els.status.html('&nbsp');
		}
		chat.updateUserEls(raw.data.name);
	},
	
	updateColor: function(raw){
		var user = chat.getUserByName(raw.data.name);
		
		user.properties.hex = raw.data.hex;
		
		user.els.base.css('color', '#'+user.properties.hex);
		chat.updateUserEls(raw.data.name);
	},
	
	updateRoom: function(raw){
		var room = chat.getRoomByName(raw.data.name);
		if( room ){
			if(raw.data.topic){
				room.properties.topic = raw.data.topic;
				if( !room.els.info.topic ){
					room.els.info.topic = $('<p />')
						.insertBefore(room.els.info.body.find("button"));
				}
				room.els.info.topic.text('Topic:'+decodeURIComponent(room.properties.topic));
				room.els.info.topic.attr('title', decodeURIComponent(room.properties.topic))
			}
			if(raw.data.priv){
				room.properties.priv = raw.data.priv;
				$("#room-settings").find("input[name=room-priv]").attr('checked', room.properties.priv);
			}
			if(raw.data.groupid){
				room.properties.groupid = raw.data.groupid;				
				if (!room.els.info.visitBtn) {
					room.els.info.visitBtn = $('<button>Visit Group</button>').button()
					.appendTo(room.els.info.body);
					room.els.info.visitBtn.click(function(e){
						window.open("http://www.rphaven.com/group.php?id="+ room.properties.groupid);
					});
				}
			}
		}
	},
	
	isRoomOwner: function(room, username){
		if( $.inArray(username, room.owners) >= 0  )
			return true;
		else
			return false;
	},
	
	isRoomOp: function(room, username){
		if( $.inArray(username, room.ops) >= 0 )
			return true;
		else
			return false;
	},
	
	kickMsg: function(data, user, pipe){
		var roomname = pipe.properties.name;
		var room = chat.getRoomByName(roomname);
		$("<div><div class='first'>[" + makeTimestamp() + "]<img src='bullet_red.png' /></div><div><span class='bold'>" + decodeURIComponent(user.properties.name) + "</span> kicked <span class='highlight'>" + decodeURIComponent(data.victim) + "</span> from " + decodeURIComponent(roomname) + " ( Reason: " + decodeURIComponent(data.msg) + " )</div></div>")
			.appendTo(room.container);
		
		chat.scrollMsg(room.container.parent());
	},
	
	banMsg: function(data, user, pipe){
		var roomname = pipe.properties.name;
		var room = chat.getRoomByName(roomname);
		$("<div><div class='first'>[" + makeTimestamp() + "]<img src='bullet_red.png' /></div><div><span class='bold'>" + decodeURIComponent(user.properties.name) + "</span> banned <span class='highlight'>" + decodeURIComponent(data.victim) + "</span> from " + decodeURIComponent(roomname) + " ( Reason: " + decodeURIComponent(data.msg) + " )</div></div>")
			.appendTo(room.container);
		
		chat.scrollMsg(room.container.parent());
	},
	
	updateAccess: function(raw){
		var user = chat.getUserByName(raw.data.name);
		var username = user.properties.name;
		var room = chat.getRoomByName(chat.userLocation[username]);
		if( room != undefined ) {
			var user = chat.getUserByName(username);
			if( raw.data.access ) {
				user.properties.access = raw.data.access;
				
				if( raw.data.access = 2 )
					room.ops.push(username);
			}
			else {
				user.properties.access = null;
				var arrPos = $.inArray(username, room.ops);
				if( arrPos >= 0 )
					room.ops.arrayRemove(arrPos);
			}
			
			chat.setRoomAccess(username, room);
		}
	},
	
	massMessage: function(raw){
		if(raw.data.type == '1' || raw.data.type == '2')
			var modalVar = false;
		if(raw.data.type == '3' || raw.data.type == '4')
			var modalVar = true;
		if(raw.data.type == '1' || raw.data.type == '3')
			var titleVar = 'Admin Mass Message from ' + raw.data.name;
		if(raw.data.type == '2' || raw.data.type == '4')
			var titleVar = 'Admin Mass Message';
		$('<div />').append('<div style="height:100%" class="innerbg smallBorders" style="padding:0;"><div style="padding:5px;"><div class="ui-state-highlight ui-corner-all" style="padding: 1em .7em;"><p><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>'+decodeURIComponent(raw.data.msg)+'</p></div></div>').dialog({
			bgiframe: true,
			title: titleVar,
			autoOpen: true,
			modal: modalVar,
			height: 300,
			width: 350
		});
	},
	
	openRoomOptions: function(roomname){
		$("#manage-room").dialog('open');
		core.request.send('GETBANS', {'room':roomname});
		var room = chat.getRoomByName( roomname );
		$("#room-settings").find("input[name=room-topic]").val( decodeURIComponent(room.properties.topic) );
		var cmd = {"name":room.properties.name};
		$("#room-settings").find("input[name=room-priv]").bind("change", function(){
			 cmd.priv = $("#room-settings").find("input[name=room-priv]").is(':checked');
		});
		$('#room-settings').submit(function(ev){
			ev.preventDefault();
			var topic = $("#room-settings").find("input[name=room-topic]").val();
			if( topic != room.properties.topic )
				cmd.topic = topic;
			core.request.send('SETROOMOPTIONS',cmd);
		});
	},
	
	populateBans: function(raw){
		var $bantable = $('#banslist');
		$bantable.find('tr:gt(0)').remove();
		if( raw.data == 0 ){
			$('<tr><td colspan="3">No one has been banned.  Maybe you should ban people. :3</td></tr>')
				.appendTo($bantable);
		}	else	{
			raw.data.users.each(function(i){				
				var html = '<tr>' +
							'<td class="clickable">'+ decodeURIComponent(i.name) +'</td>' +
							'<td>To be implemented</td>' +
							'<td>To be implemented</td>' +
							'</tr>';
				var $line = $(html).appendTo($bantable);
				
				$line.rightClick(function(ev){
					var user = chat.getUserByName(i.name);
					chat.dropdown.addOption(user, ["Unban"]);
					chat.dropdown.createDropdown(ev, user, raw.data.roomname);
				});
			});
		}
	},
	
	errorPopup: function(message){
		$("#errorDialog").dialog('open');
		$("#errorDialog").find("p").replaceWith('<p class="ui-state-error ui-corner-all"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>' + message + '</p>');
	},
	
	disconnected: function(){
		chat.errorPopup('Your connection has been lost.<br />You must refresh to reestablish a connection and log in.<br />You can close this window to copy text before refreshing.');
	},
	
	/*restoreEnd: function(){
		$(chat).bind(core.getSession('currentPipe',function(resp){
			if(resp.raw=='SESSIONS') chat.setCurrentPipe(resp.data.sessions.currentPipe);
			})
		);
	}*/
	restoreEnd: function(){
		/*$(chat).bind(core.setOptions({
				'callback':function(resp){
					if(resp.raw=='SESSIONS' && resp.data.sessions.currentPipe) chat.setCurrentPipe(resp.data.sessions.currentPipe);
				}
			})
		);
		core.getSession('currentPipe');*/
	},
	
	errorHandler: function(raw) {
		if(raw.data.code != 004 && raw.data.code != 005 && raw.data.code != 250 && raw.data.code != 301 && raw.data.code != 310 && raw.data.code != 320 && raw.data.code != 321 && raw.data.code != 330 && raw.data.code != 999)	{
			var $error = $('<div class="subAlert"><div class="close" style="float:right; color:red; font-weight:bold; height:25px; width:25px; cursor:pointer;" title="Close error">X</div>Unspecified error: ' + raw.data.code + ' ' + raw.data.value + '.  The error isn\'t an issue if things are still working fine.  If things aren\'t working fine, or the error keeps repeating, then just refresh.  If you can reproduce the problem, post it on the support blog.  Make sure it isn\'t already posted first though!</div>')
				.appendTo("#mainChat");
			$error.find('.close').click(function(ev){
				ev.preventDefault();
				$error.remove();
			})
			
		}
		else {
			if(raw.data.code == 004)
				chat.errorPopup('Your connection has been lost.<br />You must refresh to reestablish a connection and log in.<br />You can close this window to copy text before refreshing.');
			if(raw.data.code == 005)
				chat.login.nickUsed();
			if(raw.data.code == 310)
				chat.errorPopup('You do not have ownership rights to chat room.');
			if(raw.data.code == 301)
				chat.errorPopup('Topic too long.');
			if(raw.data.code == 320)
				chat.errorPopup('Status message must be 20 chars or less.  Donating will increase the limit to 100.  Some characters(spaces, commas) are escaped and count as 2-3 characters.');
			if(raw.data.code == 321)
				chat.errorPopup('Status message must be 100 chars or less. Some characters(spaces, commas) are escaped and count as 2-3 characters.');
			if(raw.data.code == 999)
				chat.errorPopup('Only donators can use this feature.');
			
			if(raw.data.code == 330)	
				$("#loginDialog").find("p").replaceWith('<p class="ui-state-error ui-corner-all" style="padding: 1em .7em;"><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span><strong>Error:</strong>Your version of the chat is too old .  You must clear your browsers cache and refresh before you may log in.</p>');
		}
	},
	
	make_admin_toolbar: function(){
		$('#top > .right').prepend(
				$('<a />').text('Admin').click(function(e){
					e.preventDefault();
					$("#adminDialog").dialog('open');
				})
			);
		$("#mass-message").submit(function(e){
			e.preventDefault();
			var msg = $("#mass-message input").val();
			var type = $("#mass-message select").val();
			
			core.request.send('MASS', {'msg':msg,'type':type});
		});
	},
	
	quit: function(){
		core.quit();
		core.initialize(core.options);
		chat.login.prompt();
	},
	
	reset: function(){
		if (core.status != 0) {
			core.clearSession();
			core.initialize(core.options);
			chat.login.prompt();
		}
	}
};

	chat.channels={
			init: function(){
				$("#create-room").submit(function(ev){
					ev.preventDefault();
					
					if($("#roomname").val() != '')
						chat.channels.joinChannel('create');
				});
				
				$("#join-room").submit(function(ev){
					ev.preventDefault();
					
					if($("#roomname").val() != '')
						chat.channels.joinChannel('join');
				});
			},
			
			openRoomlist: function(){
				$("#roomDialog").dialog('open');
				chat.channels.listChannels();
			},
		
			listChannels: function(){
				core.request.send('CLIST');
			},
			
			joinChannel: function(type){
				var target = '#create-room';
				if( type == 'join' )
					target = '#join-room';
				var roomname = $(target + "> input[name=room-name]").val();
				var pass = $(target + "> input[name=room-password]").val();
				var topic = $(target + "> input[name=room-topic]").val();
				if( topic == "" )
					topic = "None";
					
				if( roomname.replace(/[^a-zA-Z0-9]+/g,'') === roomname && roomname.length <= 32 ) {
					var wait = 0;
					if (chat.currentPubid != null) {
						var wait = 300;
					}
					var delayJoin = function() {
						if( isMobile )
							chatUI.switchTabs( $('#tabs a[href="#center"]') );
						core.join(roomname);
						//core.request.send('JOIN',{"channels":roomname,"pass":pass});
					};
					setTimeout(delayJoin,wait);
					if( type == 'create' && topic != "None"){
						var delayOptions = function() {
							var priv = false;
							var pass = false;
							core.request.send('SETROOMOPTIONS',{"name":roomname,"topic":topic});
							//core.request.send('SETROOMOPTIONS',{"name":roomname,"topic":topic,"priv":priv,"pass":pass});
						};
						setTimeout(delayOptions,1000);
					}
					
					chat.currentOptions = roomname;
				}
				else {
					chat.errorPopup('Only a-Z and 0-9 is allowed for room names.  Max name length is 32.');
				}
			},
			
			addChannels: function(raw){
				var $roomtable = $('#roomDialog tbody');
				$roomtable.find('tr:gt(0)').remove();
				if( raw.data == 0 ){
					$('<tr style="height:15px;"><td colspan="4">No rooms exist.</td></tr>')
						.appendTo($roomtable);
				}	else	{
					var num = 1;
					raw.data.each(function(i){
						var room = chat.getRoomByName(i.properties.name);
						var raw = {"data":i.properties};
						chat.updateRoom(raw);
						var html = '<tr class="clickable" style="height:15px;">' +
									'<td>'+ i.properties.nusers +'</td>' +
									'<td>'+ i.properties.passed +'</td>' +
									'<td>'+ i.properties.name +'</td>' +
									'<td>'+ decodeURIComponent(i.properties.topic) +'</td>' +
									'</tr>';
						var $line = $(html).appendTo($roomtable);
						if(i.properties.color){
							$line.css('color', '#'+i.properties.color)
						}
						
						if( num == 2){
							$line.addClass('even');
							num = 0;
						}
						
						$line.bind("click", function(){
								$("#join-room > input[name=room-name]").val(i.properties.name);
								$("#roomslist-tabs").tabs("select", 1)
							})
							.bind("dblclick", function(){
			      				chat.channels.joinChannel('join');
			    			});
						num++;
					});
				}
			},
			
			closeRoomlist: function(){
				$("#roomDialog").dialog('close');
			}
	};
	
	chat.buttons = {
			initAll: function(){
				chat.buttons.buddyList.init();
				chat.buttons.colorPicker.init();
			},
			
			topBar: {
				setName: function(){
					$('#logout').bind('click', function(event){
						chat.quit();
					});
					$('#login-name').text(decodeURIComponent(chat.user.name));
				},
				
				setUserCount: function(numusers){
					chat.buttons.topBar.count = numusers;
					chat.buttons.topBar.header = $('.header');
					chat.buttons.topBar.header.text(numusers + ' RP\'ers online.');
				},
				
				updateUserCount: function(direction){
					numusers = chat.buttons.topBar.count;
					if( direction == 'up')
						chat.buttons.topBar.count = numusers+1;
					if( direction == 'down')
						chat.buttons.topBar.count = numusers-1;
					chat.buttons.topBar.header.text(chat.buttons.topBar.count + ' RP\'ers online.');
				}
			},
			
			
			populateIgnores: function(username){
				var user = chat.getUserByName(username);
				var list = chat.buddyList.ignores;
				chat.dropdown.removeOption(user, ["Block"]);
				chat.dropdown.addOption(user, ["Unblock"]);
				
				chat.buddyList.ignores.properties.nusers+=1;
				chat.appendUserEl(username, list.els.userlist);
				list.els.usercount.text(list.properties.nusers + '-');
				
				list.properties.users.push(user.properties.name);
			},
			
		 	buddyList: {
			 		init: function(){
			 			$(".createRoom").click(function(event){
			 				event.preventDefault();
							chat.channels.openRoomlist();
			 			});
						
						$(".colorPick").click(function(e){
							chat.buttons.colorPicker.move(this);
							e.stopPropagation();
						});
						
						$("#setstatus").submit(function(event){
							event.preventDefault();
							var newStatus = $("#setstatus input").val();
							if( newStatus == '')
								newStatus = 'none';
							chat.buttons.buddyList.set_status(newStatus);
						});
			 		},
					set_status: function(newStatus) {
						core.request.send('STATUS',{'status':newStatus});
					},
					request_add: function(pubid) {
						core.request.send('REQUESTADD',{'pubid':pubid});
						var PM = chat.pm.getByPubid(pubid);
						PM.addRequest = $("<p class='sys em bold'>You have sent a buddy request.</p>")
							.appendTo(PM.container);
						chat.scrollMsg(PM.container.parent());
					},
					accept_add: function(pubid) {
						core.request.send('ACCEPTADD',{'pubid':pubid});
					},
					deny_add: function(pubid) {
						core.request.send('DENYADD',{'pubid':pubid});
					},
					add_denied: function(raw, pipe) {
						var pubid = pipe.pipe.pubid;
						var PM = chat.pm.getByPubid(pubid);
						PM.addRequest.text("Add request denied.  Future buddy requests from this user will be blocked for 24-48 hours.");
					},
					add_accepted: function(raw,pipe) {
						var pubid = pipe.pipe.pubid;
						var username = pipe.properties.name
						var PM = chat.pm.getByPubid(pubid);
						PM.addRequest.text("You and "+username+" are now buddies!");
						
						chat.buddyList.offlines.properties.users[username] = {"casttype":"uni", "pubid":pubid, "properties":{"name":username, "status":"none", "hex":"000000"}};
						var user = chat.buddyList.offlines.properties.users[username];
						chat.populateOfflines(username);
						
						var raw = {"data":{"casttype":"uni", "pubid":pubid, "name":pipe.properties.name, "status":"none", "hex":"000000"}};
						chat.setOnline(raw);
					},
					receive_add_request: function(raw, pipe) {
						var pubid = pipe.pipe.pubid;
						var PM = chat.pm.getByPubid(pubid);
						PM.addRequest = $("<p class='sys em bold'><b style='"+pipe.properties.hex+"'>" + pipe.properties.name + ":</b> has sent you a request to add you to their buddylist.  You may </p>")
							.append(
								$('<a href="#" />').text('Accept').click(function(ev){
									ev.preventDefault();
									chat.buttons.buddyList.accept_add(pubid);
								})
								.add('<span> or </span>')
								.add(
									$('<a href="#" />').text('Deny').click(function(ev){
										ev.preventDefault();
										chat.buttons.buddyList.deny_add(pubid);
									})
								)
							)
								.appendTo(PM.container);
							chat.scrollMsg(PM.container.parent());
					},
					errors: function(raw,pipe) {
						var pubid = pipe.pipe.pubid;
						var PM = chat.pm.getByPubid(pubid);
						if( raw.data.error = 101)
							$("<p class='sys em bold'>Unresponded request was already sent.</p>")
								.appendTo(PM.container);
						if( raw.data.error = 102)
							$("<p class='sys em bold'>You are buddied with "+pipe.properties.name+" already.</p>")
								.appendTo(PM.container);
						if( raw.data.error = 103)
							$("<p class='sys em bold'>Add request was already denied!</p>")
								.appendTo(PM.container);
						
						chat.scrollMsg(PM.container.parent());
					}
		 	},
			
			colorPicker: {
					init: function() {
						$("#red, #green, #blue").slider({
							orientation: 'horizontal',
							range: "min",
							max: 165,
							value: 20,
							slide: chat.buttons.colorPicker.refreshSwatch,
							change: chat.buttons.colorPicker.refreshSwatch
						});
					},
					hexFromRGB: function(r, g, b) {
						var hex = [
							r.toString(16),
							g.toString(16),
							b.toString(16)
						];
						$.each(hex, function (nr, val) {
							if (val.length == 1) {
								hex[nr] = '0' + val;
							}
						});
						return hex.join('').toUpperCase();
					},					
					refreshSwatch: function() {
						var red = $("#red").slider("value")
							,green = $("#green").slider("value")
							,blue = $("#blue").slider("value")
							,hex = chat.buttons.colorPicker.hexFromRGB(red, green, blue);
						$("#swatch").css("background-color", "#" + hex);
						$("textarea").css("color", "#" + hex);
						userOptions.color = hex;
					},					
					hexToSliders: function(hexcolor) {
						var r = parseInt(hexcolor.slice(0,2), 16);
						var g = parseInt(hexcolor.slice(2,4), 16);
						var b = parseInt(hexcolor.slice(4,6), 16);
					
						$("#red").slider("value", r);
						$("#green").slider("value", g);
						$("#blue").slider("value", b);
					},
					rgbFromCSS: function(rgbcss) {
						var _rgb = rgbcss.match(/\d+/g);
						r = parseInt(_rgb[0], 10);
						g = parseInt(_rgb[1], 10);
						b = parseInt(_rgb[2], 10);
						
						var hex = chat.buttons.colorPicker.hexFromRGB(r, g, b);
						return hex;
					},
					move: function(target){
						$("#colorPicker").show().prependTo(target);
						
						$(document).unbind('click');
						$(document).bind('click', function(e){
							chat.buttons.colorPicker.set_color(userOptions.color);
							$("#colorPicker").hide();	
							$(document).unbind('click');						
						});
					},
					set_color: function(newHex) {
						core.request.send('COLOR', {'hex': newHex});
						chat.cookie.set();
					}
			}
	};
	
	chat.imageshare = {
			request_share: function(pubid) {
				core.request.send('REQUESTSHARE',{'pubid':pubid});
				var PM = chat.pm.getByPubid(pubid);
				PM.addRequest = $("<p class='sys em bold'>You have sent an image-share request.</p>")
					.appendTo(PM.container);
				chat.scrollMsg(PM.container.parent());
			},
			accept: function(pubid) {
				core.request.send('ACCEPTSHARE',{'pubid':pubid});
			},
			deny: function(pubid) {
				core.request.send('DENYSHARE',{'pubid':pubid});
			},
			denied: function(raw,pipe) {
				var pubid = pipe.pipe.pubid;
				var PM = chat.pm.getByPubid(pubid);
				if(raw.data.name != undefined)
					PM.addRequest.text("The image-share request has been denied.");
			},
			receive_request: function(raw, pipe) {
				var pubid = pipe.pipe.pubid;
				var PM = chat.pm.getByPubid(pubid);
				PM.addRequest = $("<p class='sys em bold'><b style='"+pipe.properties.hex+"'>" + decodeURIComponent(pipe.properties.name) + ":</b> has sent you an image-share request.  You may </p>")
					.append(
						$('<a href="#" />').text('Accept').click(function(ev){
							ev.preventDefault();
							chat.imageshare.accept(pubid);
						})
						.add('<span> or </span>')
						.add(
							$('<a href="#" />').text('Deny').click(function(ev){
								ev.preventDefault();
								chat.imageshare.deny(pubid);
							})
						)
					)
						.appendTo(PM.container);
					chat.scrollMsg(PM.container.parent());
			},
			upload_response: function(json) {
				var pubid = json.pubid;
				var img = json.image;
				var type = 'upload';
				core.request.send('SHAREADDIMG',{'type':type,'url':json.image,'pubid':pubid});
				chat.imageshare.add_img(pubid, img, type);
			},
			receive_img: function(raw, pipe) {
				var pubid = pipe.pipe.pubid;
				var img = raw.data.url;
				var type = raw.data.type;
				
				chat.imageshare.add_img(pubid, img, type);
			},
			add_img: function(pubid, image, type) {
				var thumb = '';
				if( type = 'upload'){
					thumb = 'temp/th_'+image;
					image = 'temp/'+image;
				}
				else
					thumb = image;
				
				var $img = $('<img src="'+image+'" />')
					.appendTo(chat.ISs[pubid].els.imgWindow);
				var $thumbContainer = $('<div />')
					.appendTo(chat.ISs[pubid].els.thumbsScroller);
				var $thumb = $('<li class="ui-corner-all"><img src="'+thumb+'" /></li></li>')
					.appendTo($thumbContainer);
				$img.hide();
				var $deleteBtn = $('<button class="delete"><span class="ui-corner-all ui-icon ui-icon-closethick" title="Close PM">close</span></button>').button().appendTo($thumbContainer);
				$thumb.button();
				$thumbContainer.hover(function(ev){
						$deleteBtn.show();
					}, function(ev){
						$deleteBtn.hide();
					}
				);
				
				if( chat.ISs[pubid].els.imgWindow.children().length <= 1 ){
					var pos = $thumbContainer.index();
					chat.imageshare.set_current_img(pubid, pos);
				}
				if( chat.isSelf(pubid) ){
					var pos = $thumbContainer.index();
					chat.imageshare.set_current_img(pubid, pos);
				}				
				$thumb.click(function(ev){
					var pos = $thumbContainer.index();
					chat.imageshare.set_current_img(pubid, pos);
				});
				$deleteBtn.click(function(ev){
					var pos = $(this).parent().index();
					core.request.send('SHAREREMOVEIMG',{'pubid':pubid,'position':pos});
					chat.imageshare.delete_img(pubid, pos);
				});
			},
			set_current_img: function(pubid, pos){
				chat.ISs[pubid].els.imgWindow.find('img').eq(pos).show();
				chat.ISs[pubid].els.imgWindow.find('img').not(':eq('+pos+')').hide();
							
				core.request.send('SHARECURVIEW',{'pubid':pubid,'position':pos});
			},
			others_current_img: function(raw,pipe){
				var pos = raw.data.position;
				var pubid = pipe.pipe.pubid;
				var img = chat.ISs[pubid].els.thumbsScroller.find('img').eq(pos).attr('src');
				
				chat.ISs[pubid].els.curImg.find('img').attr('src', img);
				
				chat.ISs[pubid].els.curImg.click(function(ev){
					chat.imageshare.set_current_img(pubid, pos);
				});
			},
			receive_delete: function(raw,pipe){
				var pos = raw.data.position;
				var pubid = pipe.pipe.pubid;
				
				chat.imageshare.delete_img(pubid, pos);
			},
			delete_img: function(pubid, pos){
				chat.ISs[pubid].els.imgWindow.find('img').eq(pos).remove();
				chat.ISs[pubid].els.thumbsScroller.find('div').eq(pos).remove();
			},
			receive_end: function(raw, pipe){
				var pipe = pipe.pipe;
				var pubid = pipe.pubid;
				var PM = chat.pm.getByPubid(pubid);
				$("<p class='sys em bold'><b style='"+pipe.properties.hex+"'>" + decodeURIComponent(pipe.properties.name) + ":</b> has closed their image-share.</p>")
					.appendTo(PM.container);
				chat.scrollMsg(PM.container.parent());
			},
			start: function(raw,pipe){
				var pipe = pipe.pipe;
				var pubid = pipe.pubid;
				var PM = chat.pm.getByPubid(pubid);
				
				if( $('#imgshare'+pubid).length ) {
					$('#imgshare'+pubid).dialog('open');
					return false;
				}
				PM.addRequest.remove();
				chat.ISs[pubid] = {"properties": {"name":pipe.properties.name,"pubid":pubid}};
				chat.ISs[pubid].active = true;
				chat.ISs[pubid].els = {};
				
				var $imageShareDialog = $('<div id="imgshare'+pubid+'" />');
				var $topContainer = $('<div class="innerbg smallBorders share-imgs" style="padding:0 2px;" />').appendTo($imageShareDialog);
				chat.ISs[pubid].els.imgWindow = $('<div />').appendTo($topContainer);
				
				var $botContainer = $('<div class="innerbg smallBorders" style="padding:0 2px; height: 88px; margin-top:3px;" />').appendTo($imageShareDialog);
				
				chat.ISs[pubid].els.thumbsScroller = $('<ul class="share-thumbs" />').appendTo($botContainer);
				chat.ISs[pubid].els.curImg = $('<ul class="smallBorders current-image"><li class="ui-corner-all"><img width="60" height="60" src="temp/dafault.png" />Others View</li></ul>').appendTo($botContainer);
				var addThumb = function(){
					var $thumb = $('<li class="ui-corner-all"><img width="60" height="60" src="http://weblogs.wxmi.com/news/traffic/dirty-windshield/US-31-logo-75x75.jpg" /></li>');
					$thumb.appendTo(chat.ISs[pubid].els.thumbsScroller);
				};
				var resizeImgWindow = function($container){
					$topContainer.css('height', $container.height() - $botContainer.outerHeight(true) );
				};				
				var resizeThumbsWindow = function($botcontainer){
					chat.ISs[pubid].els.thumbsScroller.css('width', $botcontainer.innerWidth() - chat.ISs[pubid].els.curImg.outerWidth() -6 );
				};
				var resizeImgContainer = function() {
					chat.ISs[pubid].els.imgWindow.css('height', $topContainer.height() - $imgButtons.height());
				}
				var $iframe = $('<iframe name="uploadTarget" />').appendTo('body');
				$iframe.hide();
				var buttonsHtml = '<ul id="pmHeader" class="horiBtns">';
				buttonsHtml += '<li class="upload">Add new image</li>';
				buttonsHtml += '<li><form action="ajax_chat.php?upload&pubid='+pubid+'&userid='+chat.user.userid+'" enctype="multipart/form-data" method="POST" style="position:absolute; left: 0; opacity: 0;" target="uploadTarget">';
				buttonsHtml += '<input name="image" type="file" name="image" size="0" style="cursor:pointer;height:18px;" />';
				buttonsHtml += '</form></li>';
				buttonsHtml += '</ul>';
				var $imgButtons = $(buttonsHtml).prependTo($topContainer);
				var $uploadLink = $imgButtons.find('.upload');
				var $uploadBtn = $imgButtons.find('input[name=image]');
				var $uploadForm = $imgButtons.find('form');				
				$uploadBtn.change(function(ev){
					if($uploadBtn.val() != '')
			        	$uploadForm.submit();
				});
				
				$imageShareDialog.dialog({
			  		bgiframe: true, title: 'Image share with ' + decodeURIComponent(pipe.properties.name),
					width: 550, height: 425, position: 'right',
					resize: function(event, ui) {
						resizeImgWindow( $(this) );
						resizeThumbsWindow( $botContainer );
						resizeImgContainer();
						//chat.ISs[pubid].els.imgWindow.find('img')
					},
					beforeclose: function(event, ui) {
						core.request.send('SHARESTOP',{'pubid':pubid,'position':'REMOVE ME SOON'});
					}
				});
				resizeImgWindow( $imageShareDialog );
				resizeThumbsWindow( $botContainer );
				resizeImgContainer();
	 		}
 	};
	
	chat.dropdown = {
			createDropdown: function(clickPos, user, roomname){
				var room = null;
				var username = user.properties.name;
				room = chat.getRoomByName(roomname);
				if( !roomname && chat.currentPipe )
					room = chat.getRoomByName( chat.getCurrentPipe().name );
				var stopper = false;
				
				if( room ) {
					roomname = room.properties.name;
					if( chat.isRoomOwner(room, chat.user.name) ) {
						//make sure you aren't clicking yourself if an op or owner, just return normal menu for chat
						if( !chat.isRoomOp(room, username) && !chat.isRoomOwner(room, username) )
							chat.dropdown.addOption(user, ["Make Operator","Kick", "Ban"]);
						else if( chat.isRoomOp(room, username) )
							chat.dropdown.addOption(user, ["Remove Ops", "Kick", "Ban"]);
					}
					else if( chat.isRoomOp(room, chat.user.name) ) {
						if( !chat.isRoomOp(room, username) && !chat.isRoomOwner(room, username) )
							chat.dropdown.addOption(user, ["Kick", "Ban"]);
					}
					else {
						chat.dropdown.removeOption(user, ["Make Operator","Remove Ops","Kick", "Ban", "Unban"]);
					}
				}
				
				var html = '<ul class="ui-widget ui-widget-content ui-corner-all shadow" id="dropdownMenu">';
				html += '<li style="padding: 2px;">';
				html += '<ul class="innerbg smallBorders" />';
				html += '</li>';
				html += '</ul>';
				var buttonhtml = '<li class="listBtn ui-corner-all">Placeholder</li>';
				
				var $menu = $(html).appendTo("body");
				var $menuList = $menu.find('ul');
				$menu.bind("contextmenu",function(e){
        			return false;
   				});
				
				$.each(user.dropdownOptions, function(index, tag) {
					chat.dropdown.addListItem($menuList, user, tag, roomname);
				});
				$menuList.append('<li class="clear" />');				
				$menu.position({
				    my: "center top", of: clickPos, offset: "0 -20", collision: "fit"
				});
					
				$(document).bind("click contextmenu", function(ev){
					if( ev.target != clickPos.target)
						$menu.remove();
				});
			},
			
			addOption: function(user, newOptions){
				if( !user.dropdownOptions )
					user.dropdownOptions = [];
				
				var arrayOrder = [["View Profile","Open PM","Block","Unblock"],["Unfriend"],["Make Operator","Remove Ops"],["Kick", "Ban","Unban"]];
				var tempArray = [];
				    
				$.each(newOptions, function(index, tag) {
					if (jQuery.inArray(tag, user.dropdownOptions) == -1) {
						user.dropdownOptions.push(tag);
					}
				});
				
				$.map(arrayOrder, function(set, index){
					var i = 0;
					var innerTempArray = $.map(set, function(tag, innerIndex){
						if (jQuery.inArray(tag, user.dropdownOptions) >= 0) {
							i++;
							if(i == 1 && index > 0){
								tempArray.push("HR");
							}
							tempArray.push(tag);
						}
					});
				});
				user.dropdownOptions = tempArray;
            },
			
			removeOption: function(user, newOptions){
				if( user ){
					var arrayOrder = [["View Profile","Open PM","Block","Unblock"],["Unfriend"],["Make Operator","Remove Ops"],["Kick", "Ban","Unban"]];
					var tempArray = [];
					
					$.each(newOptions, function(index, tag) {						
						var pos = $.inArray(tag, user.dropdownOptions);
						if( pos >= 0 )
							user.dropdownOptions.arrayRemove(pos);
					});
					
					$.map(arrayOrder, function(set, index){
						var i = 0;
						var innerTempArray = $.map(set, function(tag, innerIndex){
							if (jQuery.inArray(tag, user.dropdownOptions) >= 0) {
								i++;
								if(i == 1 && index > 0){
									tempArray.push("HR");
								}
								tempArray.push(tag);
							}
						});
					});
					user.dropdownOptions = tempArray;
				}
			},
			
			addListItem: function(el, user, tag, roomname){
				if( tag == "HR"){
					$('<hr style="margin: 3px 0;"/>')
						.appendTo(el);
					return false;
				}
				var buttonhtml = '<li class="listBtn ui-corner-all">' + tag + '</li>';
				$(buttonhtml).bind("click", function(){;
					chat.dropdown.action(user, tag, roomname);
				}).hover(function(){ 
						$(this).addClass("ui-widget-header");
					},	function(){ 
						$(this).removeClass("ui-widget-header");
					})
						.appendTo(el);
			},

			action: function(userDOM, action, roomname){
				var user = chat.getUserByName(userDOM.properties.name);
				switch (action) {
					case "View Profile":{
						window.open("http://www.rphaven.com/profile.php?user="+ decodeURIComponent(userDOM.properties.name));						
						break;
					}
					case "Open PM":{
						if( !core.getPipe(user.pubid) ){
							userDOM.pipe = {pubid:userDOM.pubid,properties:userDOM.properties};
							var pipe = core.newPipe('uni', userDOM);
						}
						chat.setCurrentPMPipe(user.properties.name);
						if( !$("#pmDialog").dialog('isOpen') ) {
							$("#pmDialog").dialog('open');
						}
						if( isMobile ){
							chatUI.switchTabs( $('#tabs a[href="#pmDialog"]') );
						}
						break;
					}
					case "Block":{
						$.ajax({
							type: "POST", url: 'ajax_chat.php?ignore', dataType: 'json', 
							data: "user=" + decodeURIComponent(userDOM.properties.name) + "&accid=" + chat.user.accid,
							success: function(json) {
								if (json.error == 'true') {
									chat.errorPopup(json.msg);
								}
							}
						});
						chat.buttons.populateIgnores(userDOM.properties.name);
						chat.dropdown.addOption(user, ["Unblock"]);
						chat.dropdown.removeOption(user, ["Block","Open PM"]);
						break;
					}
					case "Unblock":{
						$.ajax({
							type: "POST", url: 'ajax_chat.php?unignore', dataType: 'json', 
							data: "user=" + decodeURIComponent(userDOM.properties.name) + "&accid=" + chat.user.accid
						});
						var pos = $.inArray(userDOM.properties.name, chat.buddyList.ignores.properties.users);
						chat.buddyList.ignores.properties.users.arrayRemove(pos);
						chat.removeUserEl(userDOM.properties.name, chat.buddyList.ignores.els.userlist);
						chat.dropdown.addOption(user, ["Block","Open PM"]);
						chat.dropdown.removeOption(user, ["Unblock"]);
						break;
					}
					case "Unfriend":{
						$.ajax({
							type: "POST", url: 'ajax_chat.php?unfriend', dataType: 'json', 
							data: "user=" + decodeURIComponent(userDOM.properties.name) + "&accid=" + chat.user.accid
						});
						var pos = $.inArray(userDOM.properties.name, chat.buddyList.offlines.properties.users);
						chat.buddyList.offlines.properties.users.arrayRemove(pos);
						chat.removeUserEl(userDOM.properties.name, '#listOfflines');
						chat.dropdown.removeOption(user, ["Unfriend"]);
						break;
					}
					case "Make Operator":{
						core.request.send('MAKEOP',{'room':roomname,'name':decodeURIComponent(userDOM.properties.name)});
						chat.dropdown.addOption(user, ["Remove Ops"]);
						chat.dropdown.removeOption(user, ["Make Operator"]);
						break;
					}
					case "Remove Ops":{
						core.request.send('REMOVEOP',{'room':roomname,'name':decodeURIComponent(userDOM.properties.name)});
						chat.dropdown.addOption(user, ["Make Operator"]);
						chat.dropdown.removeOption(user, ["Remove Ops"]);
						break;
					}
					case "Kick":{
						html = '<div class="innerbg smallBorders" style="height:100%"><form><label for="reason">Reason</label><input type="text" placeholder="Reason for kicking" id="reason" class="text ui-widget-content ui-corner-all" /></form></div>';
						$('<div />').append(html).dialog({
							bgiframe: true,
							title: "Confirm Kick",
							height: 300,
							width: 350,
							buttons: {
								'Kick': function(event) {
									var msg = $(this).find('input').val();
									core.request.send('KICK',{'msg':msg,'room':roomname,'name':decodeURIComponent(userDOM.properties.name)});
									$(this).dialog('close');
								},
								'Cancel': function(event) {
									$(this).dialog('close');
								}
							}
						});
						break;
					}
					case "Ban":{
						html = '<div class="innerbg smallBorders" style="height:100%"><form><label for="reason">Reason</label><input type="text" placeholder="Reason for banning." id="reason" class="text ui-widget-content ui-corner-all" /></form>Note:  This will ban their whole account.</div>';
						$('<div />').append(html).dialog({
							bgiframe: true,
							title: "Confirm Ban",
							height: 300,
							width: 350,
							buttons: {
								'Ban': function(event) {
									var msg = $(this).find('input').val();
									core.request.send('BAN',{'msg':msg,'room':roomname,'name':decodeURIComponent(userDOM.properties.name)});
									chat.dropdown.addOption(user, ["Unban"]);
									chat.dropdown.removeOption(user, ["Ban"]);
									$(this).dialog('close');
								},
								'Cancel': function(event) {
									$(this).dialog('close');
								}
							}
						});
						break;
					}
					case "Unban":{
						core.request.send('UNBAN',{'room':roomname,'name':decodeURIComponent(user.properties.name)});
						core.request.send('GETBANS', {'room':roomname});
						break;
					}
				}
			}
	};
	
	chat.msg = {
			writeLog: function(to, msg, type){
				if( type == 'uni' )
					var logType = 'histpm';
				else
					var logType = 'histc';
				
				$.ajax({
					type: "POST", url: 'ajax_chat.php?' + logType,
					data: "from=" + chat.user.userid + "&to=" + to + "&msg=" + msg
				});
			},
			
			cmdSend: function(data, pipe){
				core.getPipe(pipe);
					chat.msg.writeMessage(pipe, data.msg, core.user, pipe.type, 'self');
			},
			
			rawData: function(raw, pipe){
				//Is name not in ignores?
				if ($.inArray(raw.data.from.properties.name, chat.buddyList.ignores.properties.users) == -1)
			  		chat.msg.writeMessage(pipe, decodeURIComponent(raw.data.msg), raw.data.from, raw.data.pipe.casttype, 'other');
			},
			
			parseMessage: function(msg, type, pipe){
				msg = msg.replace(/</g, '&lt;');
				msg = msg.replace(/>/g, '&gt;');
				msg = msg.replace(/\n/g, convertNL("<br />"));
				msg = msg.replace(/(\[b\]|\*\*)(.*?)(\[b\]|\*\*)/g, '<strong>$2</strong>');
				//msg = msg.replace(/(\[i\]|\/\/)(.*?)(\[\/i\]|\/\/)/g, '<em>$2</em>');
				msg = msg.replace(/(?:\[i\]|\/\/)(.*?)(?:\[\/i\]|\/\/)/g, function ( str, p1, offset, s ) { if(s.charAt(offset-1) == ":" ) { return str } else { return "<em>" + p1 + "</em>" }})
				msg = msg.replace(/\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9\%])|www\d{0,3}[.]|(?:[a-z0-9\-_]+[.])+[a-z0[a-z]{2,4}\/?)(?:[^\s\(\)<>]+|\(([^\s\(\)<>]+|(\([^\s\(\)<>]+\)))*\))+(?:\(([^\s\(\)<>]+|(\([^\s\(\)<>]+\)))*\)|[^\s`\!\(\)\[\]\{\};:'"\.,<>\?������])?)/gi,function(url){
					var full_url = url;
					var extra = '';
					if( !full_url.match('^https?:\/\/') ) {
						full_url = 'http://' + full_url;
					}
					if( url.match(/\.(jpg|jpeg|png|gif)/i) ){
						extra = 'class="img-wrapper"';
					}
					else if( url.match(/\S*youtube\.com\S*v=([\w-]+)/i) ){
						extra = 'class="vid-wrapper"';
					}
					return '<a href="' + full_url + '" target="_blank" '+extra+'>' + url + '</a>';
				});
				
				if( type == 'multi' ){
					var roomname = pipe.properties.name;
					var room = chat.getRoomByName(roomname);
					if( chat.getCurrentPipe().getPubid() != pipe.getPubid() )
				   		room.tab.addClass('typing');
					
					var origMsg = msg;
					var rg = new RegExp('('+decodeURIComponent(chat.user.name)+')', 'g');
					if( accOptions.notifies.length > 0 )
						rg = new RegExp('('+decodeURIComponent(chat.user.name)+'|'+accOptions.notifies.join("|")+')', 'g');
					msg = msg.replace(rg, '<span class="highlight">$1</span>');
					if( origMsg.length != msg.length ){
						if( accOptions.notifyVol )
							play.notifySound();
						if( chat.getCurrentPipe().getPubid() != pipe.getPubid() )
				   			room.tab.addClass('newMessage');
						if( accOptions.notifyChat )
							desktopNotify('Notification from '+ roomname, msg );
					}
					if( accOptions.chatVol ){
						play.chatSound();
					}
				}
				
				return msg;
			},
			
			writeMessage: function(pipe, message, from, type, sender){
				var name = decodeURIComponent(from.properties.name);
				var msg = chat.msg.parseMessage(message, type, pipe);
				if( sender == 'other' )
					var color = from.properties.hex;
				else
					var color = userOptions.color;
				var msgEl = '';
				var pubid = pipe.pipe.pubid;
				var timestamp = makeTimestamp();
				if(type == 'uni') {
					var PM = chat.pm.getByPubid(pubid);
					
				   	msgEl = $("<p style='color:#"+ color +"'><span class='dull'>" + timestamp + "</span><b>" + name + ":</b> " + msg + "</p>")
						.appendTo(PM.container);
					
					if( chat.getCurrentPMPipe().getPubid() == pubid )
						chat.scrollMsg(PM.container.parent());
					
					if( sender == 'other' ) {
						if( accOptions.imVol )
							play.imSound();
						
						if ( !$("#pmDialog").dialog('isOpen') )
							$("#pmDialog").dialog('open');
						
						if( PM.typing ){
							PM.typing.remove();
							PM.tab.removeClass('typing');
						}
						
						if( chat.getCurrentPMPipe() ){
							if( chat.getCurrentPMPipe().getPubid() != pubid )
				   				chat.notify(PM);
						}
						else{
							chat.notify(PM);
						}
							
						if($.data(document,'idleTimer') == 'idle'){
							var idleMS = $.idleTimer('getElapsedTime');
							core.request.send('IDLERESPONSE', {"pubid":pubid,"time":idleMS});
						}
					}
					chat.logs.addMsg(pipe.properties.name, message, sender);
					if( accOptions.notifyPM )
						desktopNotify('PM from '+ name, msg );
			   	}
				else if(type == 'multi') {
					var roomname = pipe.properties.name;
					var room = chat.getRoomByName(roomname);
					msgEl = $("<div><div class='first'>[" + timestamp + "]<span style='color: #" + color + ";' title='" + makeTimestamp() + '-'+ name +"'>" + name + "</span></div><div style='color: #" + color + ";'>" + msg + "&nbsp;</div></div>")
						.appendTo(room.container);
					var msgElMsg = msgEl.find('div:eq(1)');
					
					if( sender != 'other' ){
						msgEl.addClass('self-msg');
					}
					
					msgEl.find("span:eq(0)").rightClick( function(e) {
							chat.dropdown.createDropdown(e, chat.getUserByName(from.properties.name), roomname);
						}).bind("click", function(e){
							if( e.target == this )
								chat.dropdown.action(chat.getUserByName(from.properties.name), "Open PM");
						});
					
					if( chat.getCurrentPipe().getPubid() == pubid )
						chat.scrollMsg(room.container.parent());
					
					if( chat.getCurrentPipe().getPubid() != pipe.getPubid() )
				   		room.tab.addClass('typing');
					
					//remove messages older than the amount in options.
					if( accOptions.maxMsgs ){
						var length = room.container.children().length;
						var max = accOptions.maxMsgs;
						max = ( length - max );
						room.container.children(':lt('+max+')').remove();
					}
				}
				msgEl.find('.vid-wrapper').before(
						$('<a href="#" />').text('Open in dialog box').bind('click', function(ev){
							ev.preventDefault();
							var matched = msg.match(/http:\/\/\S*?\.youtube\.com\/\S*v=([\w-]+)/i)[1];
							$('<div class="innerbg smallBorders" style="padding:0 2px;height: 100%"><object width="450" height="365"><param name="movie" value="http://www.youtube.com/v/$1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/'+matched+'" type="application/x-shockwave-flash" wmode="transparent" width="456" height="355"></embed></object></div>').dialog({
		  						bgiframe: true, width: 460, title: 'Youtube'
							})
						}).add(
							$('<span />').text(' - ')
						)
					);
				msgEl.find('.img-wrapper').before(
						$('<a href="#" />').text('Open in dialog box').bind('click', function(ev){
							ev.preventDefault();
							var matched = msg.match(/(http:\/\/\S*\.(jpg|jpeg|png|gif))/i)[0];
							$('<div class="innerbg smallBorders" style="padding:0 2px;height: 100%"><img src="'+matched+'" /></div>').dialog({
		  						bgiframe: true, title: 'Image'
							})
						}).add(
							$('<span />').text(' - ')
						)
					);
			},
			
			typing: {
		 		start: function(raw){
					var PM = chat.pm.getByName(raw.data.name);
					if( PM ){
						PM.typing = $("<p class='dull em'>" + decodeURIComponent(raw.data.name) + " is typing.</p>");
						$(PM.container).append( PM.typing );
				  		chat.scrollMsg(PM.container.parent());
						PM.tab.addClass('typing');
					}
				},
				
				stop: function(raw){
					var PM = chat.pm.getByName(raw.data.name);
					if( PM ){
						if( PM.typing )
							PM.typing.remove();
						PM.tab.removeClass('typing');
					}
				}
			},
			
			idle: {
		 		start: function(raw,pipe){
					var name = decodeURIComponent(pipe.properties.name);
					
					var msg = name+" has gone idle at "+makeTimestamp();
					chat.msg.appendSysMsg(pipe.properties.name, msg);
					
					chat.pm.getByName(pipe.properties.name).tab.addClass('idle');
				},
				
				stop: function(raw,pipe){
					var name = decodeURIComponent(pipe.properties.name);
					
					var msg = name+" has returned from being idle at "+makeTimestamp();
					chat.msg.appendSysMsg(pipe.properties.name, msg);
					
					chat.pm.getByName(pipe.properties.name).tab.removeClass('idle');
				},
				
				time: function(raw,pipe){
					var name = decodeURIComponent(pipe.properties.name);
					
					var addTenMins = raw.data.time + 600000;
					var msg = name+" has been idle for "+msToReadable(addTenMins);					
					chat.msg.appendSysMsg(pipe.properties.name, msg);
					
					chat.pm.getByName(pipe.properties.name).tab.addClass('idle');
				}
			},
			appendSysMsg: function(username, msg){
				var PM = chat.pm.getByName(username);
				
				var html = "<p>" + msg + "</p>";
				var $last = PM.container.children(':last');
				if( $last.is('div.sys') ){
					if( $last.children().length == 2 ){
						$last.prepend('<p class="expander clickable"><span>+</span>Show collapsed status updates.</p>').toggle(function(){
							$last.children().show();
							$(this).find('span').text('-');
							$last.addClass('expanded');
						},function(){
							$last.children(':not(.expander)').hide();
							$(this).find('span').text('+');
							$last.removeClass('expanded');
						});
						$last.children(':not(.expander)').hide();
					}
					var el = $(html).appendTo( PM.container.children(':last') );
					if( !$last.hasClass('expanded') ){
						if( $last.children().length > 2 )
							el.hide();
					}
				}
				else
					PM.container.append("<div class='sys em bold'>"+html+"</div>");
								
				chat.scrollMsg(PM.container.parent());
			},
			alert: function(raw){
				var username = raw.data.user_name;
				var boardid = raw.data.group_id;
				var topicid = raw.data.topic_id;
				var roomname = raw.data.room_name;
				var room = chat.getRoomByName(roomname);
				
				var msgEl = $('<div class="inner-alert"><p><span class="username">'+decodeURIComponent(username)+'</span> has posted a <a href="http://www.rphaven.com/topics.php?id='+boardid+'#topic='+topicid+'&page=1" target="_blank">new topic</a> for this group.</p></div>')
					.appendTo(room.container);
				
				msgEl.find("span.username").rightClick( function(e) {
						chat.dropdown.createDropdown(e, chat.getUserByName(username), roomname);
					}).bind("click", function(e){
						if( e.target == this )
							chat.dropdown.action(chat.getUserByName(username), "Open PM");
					});
				
				chat.scrollMsg(room.container.parent());
			}
	};
	
	chat.cookie = {
			set: function(){
				if( localStorage ){
					try {
						localStorage[chat.user.name+"settings"] = JSON.stringify(userOptions);
					}  catch (e) {
						if ( e.code == 22 || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' ) {
							chat.logs.clearOldData();
						}
					}
					try {
						localStorage[chat.user.accid+"settings"] = JSON.stringify(accOptions);
					}  catch (e) {
						if ( e.code == 22 || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' ) {
							chat.logs.clearOldData();
						}
					}
				}
				else{
					var tocookie = encodeURIComponent($.toJSON(userOptions));
					$.cookie(chat.user.name, tocookie, { path: '/', expires: 60 });
					tocookie = encodeURIComponent($.toJSON(accOptions));
					$.cookie(chat.user.accid, tocookie, { path: '/', expires: 60 });
				}
			},
			
			get: function(){
				if( localStorage ){
					//Transfer cookies to storage
					var cookie = $.cookie(chat.user.name);
					var accCookie = $.cookie(chat.user.accid);
					if( cookie != null || accCookie != null ) {
						$.cookie(chat.user.name, null);
						$.cookie(chat.user.accid, null);
						
						chat.errorPopup('Your stored settings had to be removed for an update.  You\'ll have to set them again.');
						
						var cookies = document.cookie.split(";");

					    for (var i = 0; i < cookies.length; i++) {
					    	var cookiei = cookies[i];
					    	var eqPos = cookiei.indexOf("=");
					    	var name = eqPos > -1 ? cookiei.substr(0, eqPos) : cookiei;
					    	document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT";
					    }
					}
					//If someone upgrades to a browser with cookies, this will change them to local storage.
					
					var userSettings = localStorage[chat.user.name+"settings"];
					var accSettings = localStorage[chat.user.accid+"settings"];
					if( userSettings ){
						userSettings = JSON.parse( userSettings );
						userOptions = userSettings;
					}
					if( accSettings ){
						accSettings = JSON.parse( accSettings );
						$.each(accSettings, function(id,val){
							accOptions[id] = val;
						});
					}
				}
				else {
					var cookie = $.cookie(chat.user.name);
					var accCookie = $.cookie(chat.user.accid);
					if(cookie != null) {
						var cookieJSON = $.evalJSON(decodeURIComponent(cookie));
						userOptions = cookieJSON;
					}
					if(accCookie != null) {
						var cookieJSON = $.evalJSON(decodeURIComponent(accCookie));
						//accOptions = cookieJSON;
						$.each(cookieJSON, function(id,val){
							accOptions[id] = val;
						});
					}
				}
			}
	};
	
	chat.pm = {
			create: function(username){
				var user = chat.getUserByName(username);
				var username = user.properties.name;
				
				if( !user.pm ){
					user.pm = {};
					var PM = user.pm;
					PM.container = $('<div />').html('<p>&nbsp;</p>').hide().appendTo('#pmChat');
					PM.tab = $('<div class="pmTab ui-corner-all" />').appendTo('#pmTabs');
					var buttonsHTML = "";
					buttonsHTML += "<li class='add-usr'>Add</li>";
					buttonsHTML += "<li class='view-prof'>Profile</li>";
					buttonsHTML += "<li class='imgshare'>Image-Share</li>";
					buttonsHTML += "<li class='view-logs'>View Logs</li>";
					buttonsHTML += "<li class='closepm IconBtn ui-corner-all ui-icon ui-icon-closethick' title='Close PM' style='float: right;'>close</li>";
					buttonsHTML += "<li class='block-usr' title='Block User' style='float: right;'>B</li>";
					PM.topButtons = $(buttonsHTML).hide()
						.appendTo("#pmHeader");
					var buttonList = PM.topButtons;
					buttonList.filter(".add-usr")
							.bind("click", function(){ chat.buttons.buddyList.request_add(user.pubid); });
					buttonList.filter(".view-prof")
						.bind("click", function(){ window.open("http://www.rphaven.com/profile.php?user="+ username); });
					buttonList.filter(".imgshare")
						.bind("click", function(){
							chat.imageshare.request_share(user.pubid);
						});
					buttonList.filter(".view-logs")
						.bind("click", function(){
							$("#logsDialog").dialog('open');
							chat.logs.loadUsers();
							chat.logs.loadDates(username);
							var date = new Date();
							var monthsList = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
							var month = date.getMonth();
							month = monthsList[month] + '-' + date.getFullYear();
							chat.logs.loadMsgs(username,month);
						});
					buttonList.filter(".closepm")
						.bind("click", function(){ chat.pm.close(username); });
					buttonList.filter(".block-usr")
						.bind("click", function(){ chat.dropdown.action(user, "Block"); });
						
					$('<a href="#" />')
						.text(decodeURIComponent(username))
						.click(function(event){
							event.preventDefault();
							chat.setCurrentPMPipe(username);
						}).rightClick( function(e) {
							alert(decodeURIComponent(username));
						})
						.appendTo(PM.tab);
					
					PM.close = $('<span class="ui-corner-all" title="close"><a class="ui-icon ui-icon-closethick">close</a></span>')
						.appendTo(PM.tab);
					PM.close.bind("click", function(){
						if( PM.close.css('opacity') == 1 ){
							chat.pm.close(username);
						}
					});
					PM.tab.hover(function(){
							PM.close.css('opacity', '1.0');
						},function(){
							PM.close.css('opacity', '0.1');
						});
					
					PM.input = $('<textarea name="pmInput" style="color:#'+userOptions.color+'" />').hide()
						.keydown(function(ev){
							//submit on enter, unless pressing Ctrl
							if( ev.keyCode == 13 )
								ev.preventDefault();
							if( ev.keyCode == 13 && ev.ctrlKey == true ) {
								$(this).val( $(this).val() + '\n' );
					   		}
						})
						.appendTo('#pmDialog .textarea');
					PM.input.TextAreaExpander({
						onResize : function() {
			  				resizePMtextdiv();
							chat.scrollMsg(PM.container.parent(), true);
						}
					});
					
					var msgHistory = chat.logs.loadPMHistory(username);
					if( msgHistory.length > 0 ){
						$('<p class="ui-state-highlight ui-corner-all" style="padding: 0.5em;"><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>Below is your recent message history.</p>')
							.appendTo(PM.container);
					}
					$.each( msgHistory, function(i,msg){
						$("<p style='color:#777'><span class='dull'>" + makeTimestamp(msg.d) + "</span><b>" + decodeURIComponent(msg.f) + ":</b> " + chat.msg.parseMessage(msg.m, 'uni') + "</p>")
							.appendTo(PM.container);
						chat.scrollMsg(PM.container.parent());
					});
				}
				if( !user.online ){
					//do they actually exist?  Maybe not needed.					
				}
				
				chat.pm.update(username);
				
				if( !$("#pmDialog").dialog('isOpen') )
					$("#pmDialog").dialog('open');
				if( $('#pmTabs').children().length == 2 )
					chat.setCurrentPMPipe(username);
				
				return user.pm;
			},
			update: function(username){
				var user = chat.getUserByName(username);
				var username = user.properties.name;
				var pubid = user.pubid;	
				var PM = user.pm;
				if( user.online ){
					core.request.send('SUBSCRIBE', {"pubid":pubid});
					
					PM.input.unbind('keydown.send')
						.bind('keydown.send', function(event){
							//submit on enter, unless pressing Ctrl
							if (event.keyCode == 13 && event.ctrlKey == false && $(this).val() != '') {
								var msg = $(this).val();
								if(msg.length <= 800){
									var pipe = chat.getCurrentPMPipe();
									//this is bad way to do it..
									if( pipe == 'undefined' ){
										chat.setCurrentPMPipe(username);
									}
									pipe.send(msg);
									$(this).val('');
									chat.msg.writeLog(username, msg, 'uni');
								}
								else{
									$(PM.container).append("<p class='sys em bold'>Message is too long.</p>");
									chat.scrollMsg(PM.container.parent());
								}
							}
						});
						
					PM.input.typeWatch({
						start: function startTyping(){
							//add a length to this for "l" for how much someone has typed.
							core.request.send('SENDTYPINGSTART', {"pubid":pubid,'l':0});
						},
						callback: function finishedTyping() {
							core.request.send('SENDTYPINGSTOP', {"pubid":pubid,'l':0});
						}
					});
				}
				else /* if not online */ {
					PM.tab.removeClass('idle');
					PM.tab.addClass('offline');
					
					PM.input.unbind('keydown.send')
						.bind('keydown.send', function(event){
							//submit on enter, unless pressing Ctrl
							if (event.keyCode == 13 && event.ctrlKey == false && $(this).val() != '') {
								$this = $(this);
								var msg = $this.val();
								if( msg.length <= 800 ){
									$.ajax({
										type: "POST", url: 'ajax_chat.php?offline_msg', dataType: 'json', 
										data: "from=" + chat.user.userid + "&to=" + username + "&msg=" + msg,
										success: function(json){
											if( json.error )
												$(PM.container).append("<p class='sys em bold'>Error: " + json.msg + ".</p>");
											else {
												$(PM.container).append("<p class='sys em bold'>\""+msg+"\" left for " + decodeURIComponent(user.properties.name) + ".<br />They'll receive it the next time they log in.</p>");
												$this.val('');
												chat.logs.addMsg(username, msg, 'self');
											}
											chat.scrollMsg(PM.container.parent());
										}
									});
								}
								else{
									$(PM.container).append("<p class='sys em bold'>Message too long.</p>");
									chat.scrollMsg(PM.container.parent());
								}
							}
						});
						
					PM.input.unbind('keydown.typeWatch');
				}
			},
			
			close: function(username){
				var user = chat.getUserByName(username);
				var pubid = user.pubid;
				var PM = user.pm;
				
				chat.pm.update(username);
				if( user.online )
					core.request.send('UNSUBSCRIBE', {"pubid":pubid});
				
				$.each(PM, function(){
					$(this).remove();
				});
				delete user.pm;
				
				$('#pmTabs').children('div').each(function(){   
					$(this).find("a").click();
					return false;
				});
				
				if( $('#pmTabs').children().length == 1 )
					$("#pmDialog").dialog('close');
				
				core.delPipe(pubid);
			},
			
			getByPubid: function(pubid){
				var username = chat.usersByPubid[pubid];
				var user = chat.getUserByName(username);
				return user.pm;
			},
			
			getByName: function(username){
				var user = chat.getUserByName(username);
				return user.pm;
			}
	};
	
	$(".open-logs").click(function(ev){
		ev.preventDefault();
		$("#logsDialog").dialog('open');
		chat.logs.loadUsers();
	});
	if( localStorage ) {
		if( localStorage["users"] )
			localStorage.clear();
		chat.logs = {
			clearOldData: function(){
				alert("Logs limit exceeded, data is being dumped.  This may take a while.");
				var dialog = $('<div />').dialog({height:470,width:750});
				var contents = $('<div class="innerbg ui-corner-all"/>').appendTo(dialog);
				$('<p class="error">Below is your oldest month of data.  It has been deleted from logs, but you can copy/paste it to a document on your computer if you wish to save it.</p>').appendTo(contents);
								
				var posInArray = function(arrayName,arrayItem)
				{
					for( var i = 0; i < arrayName.length; i++ ){ 
						if( arrayName[i] == arrayItem )
							return i;
					}
				}
				var monthsList = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
				var oldestYear = 2099;
				var oldestMonth = 12;
				for( var key in localStorage ) {
					var year = key.slice(-4);
					if( year < oldestYear )
						oldestYear = year;
					if( year == oldestYear ){						
						var monthString = key.match(/([A-Z][a-z]*)-(\d+)$/)[1];
						var monthToInt = posInArray(monthsList, monthString);
						if( monthToInt < oldestMonth )
							oldestMonth = monthToInt;
					}
				}
				var searchString = monthsList[oldestMonth]+"-"+oldestYear; // get that April-2011 looking thing.
				for( var key in localStorage ) {
					if( key.slice(-searchString.length) == searchString ) { //checks to see if the end of the string is exactly the same.
						var keysData = localStorage[key];
						$.each( JSON.parse(keysData), function(i,msg){
							$("<p><span class='dull'>" + makeTimestamp(msg.d) + "</span><b>" + decodeURIComponent(msg.f) + ":</b> " + msg.m + "</p>")
								.appendTo(contents);
						});
						$("<p>-------------------------</p><p>-------------------------</p><p>-------------------------</p>").appendTo(contents);
						localStorage.removeItem(key);
					}
					if( key.slice(-6) == "months" ) {
						var testkey = key;
						$.each( JSON.parse(localStorage[key]), function(i,month){
							if( month == searchString ){
								//console.log(month+' '+i);
								var newArray = JSON.parse(localStorage[testkey]);
								newArray.arrayRemove(i);
								if( newArray.length == 0 )
									localStorage.removeItem(testkey);
								else 
									localStorage[testkey] = JSON.stringify(newArray);
							}
						});
					}
				}
			},
			addMsg: function(username,message,sender,unixtime){
				var date = unixtime ? new Date(unixtime * 1000) : new Date();
				var monthsList = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
				var month = date.getMonth();
				month = monthsList[month] + '-' + date.getFullYear();
				
				chat.logs.addUser(username);
				chat.logs.addDate(username, month);
				
				var self = chat.user.name;
				
				var logSession = localStorage[chat.user.accid+username.toLowerCase() + month] ? JSON.parse(localStorage[chat.user.accid+username.toLowerCase() + month]) : [];
				var f = sender == 'other' ? username : self;
				logSession.push({"f":f, "m":message, "d":Math.round(date.getTime() / 1000), "o":0});
				
				try {
					localStorage[chat.user.accid + username.toLowerCase() + month] = JSON.stringify(logSession);
				}  catch (e) {
					if ( e.code == 22 || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' ) {
						chat.logs.clearOldData();
					}
				}
			},
			addUser: function(username){
				var users = localStorage[chat.user.accid+"users"] ? JSON.parse(localStorage[chat.user.accid+"users"]) : [];					
				if( $.inArray(username, users) == -1 ){
					users.push( username );
					users.sort();
				}
				try {
					localStorage[chat.user.accid+"users"] = JSON.stringify(users);
				}  catch (e) {
					if ( e.code == 22 || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' ) {
						chat.logs.clearOldData();
					}
				}
			},
			addDate: function(username,month) {
				var months = localStorage[chat.user.accid+username.toLowerCase()+"months"] ? JSON.parse(localStorage[chat.user.accid+username.toLowerCase()+"months"]) : [];				
				if( $.inArray(month, months) == -1 ){
					months.push( month );
				}
				try {
					localStorage[chat.user.accid+username.toLowerCase()+"months"] = JSON.stringify(months);
				}  catch (e) {
					if ( e.code == 22 || e.name == 'NS_ERROR_DOM_QUOTA_REACHED' ) {
						chat.logs.clearOldData();
					}
				}
			},
			loadUsers: function() {
				$("#logsDialog .left .content").children().remove();
				var users = localStorage[chat.user.accid+"users"];
				if( users ) {
					//users = JSON.parse(users);
					$.each( JSON.parse(users), function(i,val){
						var el = $('<a>'+decodeURIComponent(val)+'</a>')
							.click(function(ev){
								ev.preventDefault();
								chat.logs.loadDates(val);
						});
						el.appendTo("#logsDialog .left .content");
					});				
				}
			},
			loadDates: function(username) {
				$("#logsDialog .right .content").children().remove();
				$("#logsDialog .right .logs").children().remove();
				$("#logsDialog .right .head h2").text( 'Logs for '+decodeURIComponent(username) );
				var dates = localStorage[chat.user.accid+username.toLowerCase()+"months"];
				if( dates ) {
					//dates = JSON.parse(dates);
					$.each( JSON.parse(dates), function(i,month){
						var el = $('<a>'+decodeURIComponent(month)+'</a>')
							.click(function(ev){
								ev.preventDefault();
								chat.logs.loadMsgs(username,month);
							});
						el.appendTo("#logsDialog .right .content");
					});
				}
			},
			loadMsgs: function(username,month){
				$("#logsDialog .right .logs").children().remove();
				var msgs = localStorage[chat.user.accid+username.toLowerCase()+month];
				if( msgs ){
					$.each( JSON.parse(msgs), function(i,msg){
						$("<p><span class='dull'>" + makeTimestamp(msg.d) + "</span><b>" + decodeURIComponent(msg.f) + ":</b> " + chat.msg.parseMessage(msg.m, 'uni') + "</p>")
							.appendTo("#logsDialog .right .logs");
					});
				}
			},
			loadPMHistory: function(username){
				var date = new Date();
				var monthsList = ["January", "Febuary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
				var month = date.getMonth();
				month = monthsList[month] + '-' + date.getFullYear();
				
				var msgs = localStorage[chat.user.accid+username.toLowerCase()+month] ? JSON.parse(localStorage[chat.user.accid+username.toLowerCase()+month]) : [];	
				var len = msgs.length;
				return msgs.slice( (len - 10) , len);
			}
		};
		/*$('#transport-method').change(function(ev){
			$this = $(this);
		});*/
	}
	else {
		chat.logs = {
			addMsg: function(){},
			loadUsers: function(){ alert('Your browser does not support this.'); },
			loadDates: function(){},
			loadMsgs: function(){},
			loadPMHistory: function(){}
		};
	}
	
	$('#lfrp button.unlist').click(function(ev){
		ev.preventDefault();
		core.request.send('ADDADVERT',{'msg':'','o':0});
		$("#lfrp").find('tr > td:first-child').each(function(el){
			var $this = $(this);
			if( $this.text() == decodeURIComponent(chat.user.name) )
				$this.parent().remove()
		});
	});
	$('#lfrp button.submit').click(function(ev){
		ev.preventDefault();
		var $dialog = $("#lfrp");
		var o = 0;
		//handle errors, else go ahead
		if( $dialog.find('input[name=clean-ad]').attr('checked') && $dialog.find('input[name=dirty-ad]').attr('checked') ){
			$("#createAd p").text("You can't select both options.");
		}
		else if( !$dialog.find('input[name=clean-ad]').attr('checked') && !$dialog.find('input[name=dirty-ad]').attr('checked') ) {
			$("#createAd p").text("You must select an option.");
		}
		else if( $dialog.find('textarea').val().length > 600 ) {
			$("#createAd p").text("Advert is too long.  It must be under 600 characters.");
		}
		else {
			if( $dialog.find('input[name=clean-ad]').attr('checked') )
				o = 0;
			if( $dialog.find('input[name=dirty-ad]').attr('checked') )
				o = 1;
			var msg = $dialog.find('textarea').val();
			core.request.send('ADDADVERT',{'msg':msg,'o':o});
			
			//append new msg instead of refreshing.
			if( msg != '' && msg != 'Advert'){
				$("#lfrp").find('tr > td:first-child').each(function(el){
					var $this = $(this);
					if( $this.text() == decodeURIComponent(chat.user.name) )
						$this.parent().remove()
				});
				
				var tab = '#clean-ads';
				if(o == 1)
					tab = '#dirty-ads';
				var $advertsTable = $('#lfrp '+tab+' tbody');
				var user = chat.getUserByName(chat.user.name);
				var html = '<tr class="clickable" style="height:15px;color:#'+user.properties.hex+'">' +
							'<td>'+ decodeURIComponent(user.properties.name) +'</td>' +
							'<td>'+ msg +'</td>' +
							'<td>to be added</td>' +
							'</tr>';							
				var $line = $(html).appendTo($advertsTable);
				$line.bind("click", function(e){
						chat.dropdown.action(user, "Open PM");
				  	}).rightClick(function(e){
						chat.dropdown.createDropdown(e, user);
				 	});
			}
			
		}
	});
	$(".open-lfrp").click(function(ev){
		ev.preventDefault();
		$("#lfrp").dialog('open');
		core.request.send('ALIST',{'o':0});
		$("#lfrp-tabs").bind( "tabsselect", function(ev, ui) {
			core.request.send('ALIST',{'o':ui.index});
		});
	});
	$(".hide-notification, .disable-notification").click(function(ev){
		$("#notification").slideUp();
	});
	$(".disable-notification").click(function(ev){
		accOptions.disableNotification = true;
	});
	chat.lfrp = {
		newAdvert: function(raw){
			//should make this name..
			var username = decodeURIComponent(raw.data.user);
			$("#notification .msg").text(username + ' has posted a new RP advert.');
			$("#notification").slideDown();
			var hideNotification = function(){
				$("#notification").slideUp();
			};
			setTimeout(hideNotification,45000);
		},
		addAdverts: function(raw){			
			var o = raw.data[0].o;
			var tab = '#clean-ads';
			if(o == 1)
				tab = '#dirty-ads';
			var $advertsTable = $('#lfrp '+tab+' tbody');
			
			$advertsTable.find('tr:gt(0)').remove();
			if( raw.data == 0 ){
				$('<tr style="height:15px;"><td colspan="3">No rooms exist.</td></tr>')
					.appendTo($advertsTable);
			}	else	{
				var num = 1;
				raw.data.each(function(i){
					var user = chat.getUserByName(i.username);
					var html = '<tr class="clickable" style="height:15px;color:#'+user.properties.hex+'">' +
								'<td>'+ decodeURIComponent(i.username) +'</td>' +
								'<td>'+ decodeURIComponent(i.msg) +'</td>' +
								'<td>to be added</td>' +
								'</tr>';
					var $line = $(html).appendTo($advertsTable);
					$line.bind("click", function(e){
							chat.dropdown.action(user, "Open PM");
					  	}).rightClick(function(e){
							chat.dropdown.createDropdown(e, user);
					 	});
					
					if( num == 2){
						$line.addClass('even');
						num = 0;
					}
					num++;
				});
			}
		}
	};

});

