Date.prototype.getFormatedString = function(){
	return "(" + 
			(this.getHours()   < 10 ? "0":"") + this.getHours()   + ":" + 
			(this.getMinutes() < 10 ? "0":"") + this.getMinutes() + ":" +
			(this.getSeconds() < 10 ? "0":"") + this.getSeconds() + "&nbsp;" +
			(this.getDate()    < 10 ? "0":"") + this.getDate()    + "/" +
			(this.getMonth()   < 9  ? "0":"") + (this.getMonth() + 1) + "/" +
			this.getFullYear() + ")";
};
Date.prototype.getHoursAndMinutes = function(){
	return (this.getHours()   < 10 ? "0":"") + this.getHours()   + ":" + 
	       (this.getMinutes() < 10 ? "0":"") + this.getMinutes();
};

String.prototype.nbsp = function(){
	return String.fromCharCode(160);
};

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

String.prototype.nl2br = function(){
	return '<p>' + this.replace(/\r\n/gi, '\n')
	                   .replace(/\n{3,}/gi, '\n\n')
					   .replace(/\n\n/gi, '</p><p>')
					   .replace(/([^\n])\n([^\n])/gi, '$1<br />$2') + '</p>';
};

String.prototype.br2nl = function(){
	return this.replace(/<br[ ]?\/?>/gi, '\n');
};

String.prototype.htmlspecialchars_decode = function(){
	return this
			.replace(/&#039;/gi, String.fromCharCode(39))
			.replace(/&lt;/gi,    '<')
			.replace(/&gt;/gi,    '>')
			.replace(/&amp;/gi,   '&')
			.replace(/&quot;/gi,  '"');
};
String.prototype.htmlspecialchars_encode = function(){
	return this
			.replace(/</gi, '&lt;')
			.replace(/>/gi, '&gt;')
			.replace(/&/gi, '&amp;')
			.replace(/"/gi, '&quot;')
			.replace(/'/gi, '&#039;');
};
String.prototype.autolink = function(){
	return this.replace(/((mailto\:|(news|(ht|f)tp(s?))\:\/\/){1}\S+)/gi, '<a href="$1" target="_blank">$1</a>');
}

// this object is Window object, you need to use unload inside widget and query methods using this in context of widget
//$(window).unload(function() {this.messages_ajax.abort();} );
//$(window).unload(function() {this.contacts_ajax.abort();} );

var smiley = {
	'aa' : {text:"O:-)"       , regexp: /O(:-?|=)\)/gi },
	'ab' : {text:":-)"        , regexp: /(^|[^O])(:-?|=)\)/g },
	'ac' : {text:":-("        , regexp: /[:;]-?\(/g },
	'ad' : {text:";-)"        , regexp: /;-\)/g },
	'ae' : {text:":-P"        , regexp: /(:-?|=)P/gi },
	'af' : {text:"8-)"        , regexp: /(8-\))/g },
	'ag' : {text:":-D"        , regexp: /(:-?|=)D/g },
	'ah' : {text:":-["        , regexp: /(:-?|=)\[/g },
	'ai' : {text:"=-0"        , regexp: /[=:]-[O0]|o_o/gi },
	'aj' : {text:":-*"        , regexp: /(:-?|=)\*/g },
	'ak' : {text:":'("        , regexp: /:'\(/g },
	'al' : {text:":-X"        , regexp: /:-x/gi },
	'am' : {text:">:o"        , regexp: />:o/g },
	'an' : {text:":-|"        , regexp: /(:-?|=)\|/g },
	'ao' : {text:":-/"        , regexp: /(:-|=)(\/|\\)/g },
	'ap' : {text:"*JOKINGLY*" , regexp: /\*JOKINGLY\*/g },
	'aq' : {text:"]:->"       , regexp: /\]:->/g },
	'ar' : {text:"[:-}"       , regexp: /\[:-\}/g },
	'as' : {text:"*KISSED*"   , regexp: /\*KISSED\*/g },
	'at' : {text:":-!"        , regexp: /:-!/g },
	'au' : {text:"*TIRED*"    , regexp: /\*TIRED\*/g },
	'av' : {text:"*STOP*"     , regexp: /\*STOP\*/g },
	'aw' : {text:"*KISSING*"  , regexp: /\*KISSING\*/g },
	'ax' : {text:"@}->--"     , regexp: /@\}->--/g },
	'ay' : {text:"*THUMBS UP*", regexp: /\*THUMBS UP\*/g },
	'az' : {text:"*DRINK*"    , regexp: /\*DRINK\*/g },
	'ba' : {text:"*IN LOVE*"  , regexp: /\*IN LOVE\*/g },
	'bb' : {text:"@="         , regexp: /@=/g },
	'bc' : {text:"*HELP*"     , regexp: /\*HELP\*/g },
	'bd' : {text:"\\m/"       , regexp: /\\m\//g },
	'be' : {text:"%)"         , regexp: /%\)/g },
	'bf' : {text:"*OK*"       , regexp: /\*OK\*/g },
	'bg' : {text:"*WASSUP*"   , regexp: /\*(WASSUP|SUP)\*/g },
	'bh' : {text:"*SORRY*"    , regexp: /\*SORRY\*/g },
	'bi' : {text:"*BRAVO*"    , regexp: /\*BRAVO\*/g },
	'bj' : {text:"*ROFL*"     , regexp: /\*(ROFL|LOL)\*/g },
	'bk' : {text:"*PARDON*"   , regexp: /\*PARDON\*/g },
	'bl' : {text:"*NO*"       , regexp: /\*NO\*/g },
	'bm' : {text:"*CRAZY*"    , regexp: /\*CRAZY\*/g },
	'bn' : {text:"*DONT_KNOW*", regexp: /\*(DONT_KNOW|UNKNOWN)\*/g },
	'bo' : {text:"*DANCE*"    , regexp: /\*DANCE\*/g },
	'bp' : {text:"*YAHOO*"    , regexp: /\*YAHOO!?\*/g },
	'bq' : {text:"*HI*"       , regexp: /\*(HI|HELLO)\*/g },
	'br' : {text:"*BYE*"      , regexp: /\*BYE\*/g },
	'bs' : {text:"*YES*"      , regexp: /\*YES\*/g },
	'bt' : {text:";D"         , regexp: /;D|\*ACUTE\*/g },
	'bu' : {text:"*WALL*"     , regexp: /\*(WALL|DASH)\*/g },
	'bv' : {text:"*WRITE*"    , regexp: /\*(WRITE|MAIL)\*/g },
	'bw' : {text:"*SCRATCH*"  , regexp: /\*SCRATCH\*/g }
};


// Messenger jQuery Plugin

(function($) {
	var defaults = { option: true },
		
		uiMessengerClasses =
			'ui-messenger ' +
			'ui-widget ' +
			'ui-widget-content ' +
			'ui-corner-all ';
		
		uiChatWindowClasses =
			'ui-chatwindow ' +
			'ui-widget ' +
			'ui-widget-content ' +
			'ui-corner-all ';

	$.widget("ui.messenger", {
		
		_init: function() {
			this.originalTitle = this.element.attr('title');

			var self = this,
				options = this.options,
	
				title = options.title || this.originalTitle || '&nbsp;',
				titleId = $.ui.messenger.getTitleId(this.element),
				
				uiMessengerPlaceholder = this.element
					.css({
						position: 'relative'
					});
	
				uiMessenger = (this.uiMessenger = $('<div/>'))
					.appendTo(uiMessengerPlaceholder)
					.hide()
					.addClass(uiMessengerClasses + options.messengerClass)
					.css({ position: 'absolute', overflow: 'hidden', zIndex: options.zIndex})
					.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
						(options.closeOnEscape && event.keyCode
							&& event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
					})
					.attr({ role: 'messenger', 'aria-labelledby': titleId })
					.mousedown(function(event) { self.moveToTop(false, event); }),
				
				uiMessengerTitlebar = (this.uiMessengerTitlebar = $('<div></div>'))
					.addClass('ui-messenger-titlebar ui-widget-header ui-corner-all ui-helper-clearfix')
					.prependTo(uiMessenger),
					
				uiMessengerTitlebarClose = $('<a href="#"/>')
					.addClass('ui-messenger-titlebar-close ui-corner-all')
					.attr('role', 'button')
					.hover(
						function() {uiMessengerTitlebarClose.addClass('ui-state-hover');},
						function() {uiMessengerTitlebarClose.removeClass('ui-state-hover');}
					)
					.focus(function() {
						uiMessengerTitlebarClose.addClass('ui-state-focus');
					})
					.blur(function() {
						uiMessengerTitlebarClose.removeClass('ui-state-focus');
					})
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						self.close(event);
						uiChatWindow.hide();
						
						return false;
					})
					.appendTo(uiMessengerTitlebar),
				
				uiMessengerTitlebarCloseText = (this.uiMessengerTitlebarCloseText = $('<span/>'))
					.addClass('ui-icon ui-icon-closethick')
					.text(options.closeText)
					.appendTo(uiMessengerTitlebarClose),
					
				uiSortContacts = $('<a href="#"/>')
					.addClass('ui-messenger-titlebar-shuffle ui-corner-all')
					.attr('role', 'button')
					.hover(
						function() {uiSortContacts.addClass('ui-state-hover');},
						function() {uiSortContacts.removeClass('ui-state-hover');}
					)
					.focus(function() {
						uiSortContacts.addClass('ui-state-focus');
					})
					.blur(function() {
						uiSortContacts.removeClass('ui-state-focus');
					})
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						if(self.options.sortorder == 'FL') self.options.sortorder = 'LF';
						else self.options.sortorder = 'FL';
						self._renderContactsList();
						return false;
					})
					.appendTo(uiMessengerTitlebar),
				
				uiSortContactsText = (this.uiSortContactsText = $('<span/>'))
					.addClass('ui-icon ui-icon-shuffle')
					.text(options.sortText)
					.appendTo(uiSortContacts),
					
				uiOnlineOffline = (this.uiOnlineOffline = $('<a href="#"/>'))
					.addClass('ui-messenger-titlebar-online ui-corner-all' + 
							  (options.online ? ' ui-state-focus online' : ''))
					.attr('role', 'button')
					.attr('title', options.online ? options.onlineText : options.offlineText)
					.hover(
						function() {
							if(!options.online) uiOnlineOffline.addClass('ui-state-hover');
						},
						function() {
							if(!options.online) uiOnlineOffline.removeClass('ui-state-hover');
						}
					)
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						self._toggleStatus(options.online);
						return false;
					})
					.appendTo(uiMessengerTitlebar),
				
				uiOnlineOfflineText = (this.uiOnlineOfflineText = $('<span/>'))
					.addClass('ui-icon ui-icon-person ' + 
							  (options.online ? 'online' : 'offline'))
					.text(options.online ? options.onlineText : options.offlineText)
					.appendTo(uiOnlineOffline),
				
				uiMessengerTitle = $('<span/>')
					.addClass('ui-messenger-title')
					.attr('id', titleId)
					.html(title)
					.prependTo(uiMessengerTitlebar),
					
				uiMessengerContent = (this.uiMessengerContent = $('<div></div>'))
					.show()
					.addClass('ui-messenger-content ui-widget-content')
					.appendTo(uiMessenger),
				
				uiConversationsTitle = $('<h3/>')
					.addClass('ui-conversations-title')
					.text(options.conversationsText)
					.appendTo(uiMessengerContent),
					
				uiConversationsContent = (this.uiConversationsContent = $('<div></div>'))
					.show()
					.addClass('ui-conversations-content ui-widget-content')
					.appendTo(uiMessengerContent),
				
				uiOnlineTitle = $('<h3/>')
					.addClass('ui-online-title open')
					.text(options.onlineText)
					.mousedown(function(ev) { ev.stopPropagation(); })
					.click(function(event) {
						event.stopPropagation();
						if($(this).hasClass('open')){
							$(this).removeClass('open');
							$(this).addClass('close');
							uiOnlineContent.hide("slow");
						}else{
							$(this).removeClass('close');
							$(this).addClass('open');
							uiOnlineContent.show("slow");
						}
					})
					.appendTo(uiMessengerContent),
					
				uiOnlineContent = (this.uiOnlineContent = $('<div></div>'))
					.show()
					.addClass('ui-online-content ui-widget-content')
					.appendTo(uiMessengerContent),
				
				uiOfflineTitle = $('<h3/>')
					.addClass('ui-offline-title close')
					.text(options.offlineText)
					.mousedown(function(ev) { ev.stopPropagation(); })
					.click(function(event) {
						event.stopPropagation();
						if($(this).hasClass('open')){
							$(this).removeClass('open');
							$(this).addClass('close');
							uiOfflineContent.hide("slow");
						}else{
							$(this).removeClass('close');
							$(this).addClass('open');
							uiOfflineContent.show("slow");
						}
					})
					.appendTo(uiMessengerContent),
					
				uiOfflineContent = (this.uiOfflineContent = $('<div></div>'))
					.hide()
					.addClass('ui-offline-content ui-widget-content')
					.appendTo(uiMessengerContent),
				
				uiChatWindow = (this.uiChatWindow = $('<div/>'))
					.appendTo(uiMessengerPlaceholder)
					.hide()
					.addClass('ui-chatwindow-resize '+uiChatWindowClasses + options.chatWindowClass)
					.css({ position: 'absolute', left: options.width + 10, zIndex: options.zIndex + 1 })
					.attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
						(options.closeOnEscape && event.keyCode
							&& event.keyCode == $.ui.keyCode.ESCAPE && self.close(event));
					}),
				
				uiChatWindowTitlebar = (this.uiChatWindowTitlebar = $('<div></div>'))
					.addClass('ui-messenger-titlebar ui-widget-header ui-corner-all ui-helper-clearfix' )
					.appendTo(uiChatWindow),
					
				uiChatWindowClose = $('<a href="#"/>')
					.addClass('ui-messenger-titlebar-close ui-corner-all')
					.attr('role', 'button')
					.hover(
						function() {uiChatWindowClose.addClass('ui-state-hover');},
						function() {uiChatWindowClose.removeClass('ui-state-hover');}
					)
					.focus(function() {
						uiChatWindowClose.addClass('ui-state-focus');
					})
					.blur(function() {
						uiChatWindowClose.removeClass('ui-state-focus');
					})
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						self._removeConversation();
						return false;
					})
					.appendTo(uiChatWindowTitlebar),
				
				uiChatWindowCloseText = (this.uiChatWindowCloseText = $('<span/>'))
					.addClass('ui-icon ui-icon-closethick')
					.text(options.closeText)
					.appendTo(uiChatWindowClose),
				
				uiChatWindowTitle = $('<span/>')
					.addClass('ui-messenger-title')
					.attr('id', titleId)
					.html('Chat')
					.prependTo(uiChatWindowTitlebar),
					
				uiChatWindowContent = (this.uiChatWindowContent = $('<div></div>'))
					.show()
					.addClass('ui-chatwindow-content ui-widget-content')
					.appendTo(uiChatWindow),
					
				uiChatWindowBody = (this.uiChatWindowBody = $('<div></div>'))
					.show()
					.css({overflow: 'auto', height: 100})
					.addClass('ui-chatwindow-resize ui-chatwindow-body ui-widget-content')
					.appendTo(uiChatWindowContent),
					
				uiChatWindowInnerBody = (this.uiChatWindowInnerBody = $('<table></table>'))
					.show()
					.attr('border',0)
					.attr('cellpadding',0)
					.attr('cellspacing',0)
					.addClass('ui-chatwindow-inner')
					.appendTo(uiChatWindowBody),
					
				uiChatWindowText = (this.uiChatWindowText = $('<div></div>'))
					.show()
					.addClass('ui-chatwindow-text')
					.appendTo(uiChatWindowContent),
					
				uiChatWindowSmiley = $('<a href="#"/>')
					.addClass('ui-messenger-smiley ui-corner-all')
					.attr('role', 'button')
					.text(options.smileyText)
					.hover(
						function() {uiChatWindowSmiley.addClass('ui-state-hover');},
						function() {uiChatWindowSmiley.removeClass('ui-state-hover');}
					)
					.focus(function() {
						uiChatWindowSmiley.addClass('ui-state-focus');
					})
					.blur(function() {
						uiChatWindowSmiley.removeClass('ui-state-focus');
					})
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						self.uiChatSmileyBlock.show();
						var button      = $(this),
							placeOffset = uiMessengerPlaceholder.offset(),
							thisOffset  = button.offset(),
							x           = thisOffset.left - placeOffset.left + button.width(),
							y           = thisOffset.top  - placeOffset.top  + button.height();
							
						self.uiChatSmileyBlock.css({'top':y,'left':x});
						$("body").one("click", function(){
							self.uiChatSmileyBlock.hide();
						});
						return false;
					})
					.appendTo(uiChatWindowText),
				
				uiChatSmileyBlock = (this.uiChatSmileyBlock = $('<div></div>'))
					.hide()
					.css({ position: 'absolute', overflow: 'hidden', zIndex: options.zIndex + 3})
					.addClass('ui-smiley-block ui-widget-content')
					.appendTo(uiMessengerPlaceholder),
					
				uiChatWindowTextarea = $('<textarea></textarea>')
					.show()
					.addClass('ui-chatwindow-textarea')
					.keydown(function(event) {
						if ((event.keyCode == $.ui.keyCode.ENTER || event.keyCode == 3) && !event.shiftKey){
							self._sendMessage();
							return false;
						}else if((event.keyCode == $.ui.keyCode.ENTER || event.keyCode == 3) && event.shiftKey){
							
							//uiChatWindowTextarea.val(uiChatWindowTextarea.val() + '\n');
						}
						
					})
					.keyup(function(event) {
						if (event.keyCode > 47 && event.keyCode < 91){
							if(self.send_typing) self._sendTyping(true);
							
						}else if(event.keyCode == $.ui.keyCode.BACKSPACE && $.trim(this.value) == ''){
							self._sendTyping(false);
						}
					})
					.appendTo(uiChatWindowText),
					
				uiChatWindowSend = $('<a href="#"/>')
					.addClass('ui-messenger-send ui-corner-all')
					.attr('role', 'button')
					.text(options.sendText)
					.hover(
						function() {uiChatWindowSend.addClass('ui-state-hover');},
						function() {uiChatWindowSend.removeClass('ui-state-hover');}
					)
					.focus(function() {
						uiChatWindowSend.addClass('ui-state-focus');
					})
					.blur(function() {
						uiChatWindowSend.removeClass('ui-state-focus');
					})
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(event) {
						self._sendMessage();
						return false;
					})
					.appendTo(uiChatWindowText),
					
				uiChatWindowClear = $('<div></div>')
					.addClass('clear')
					.appendTo(uiChatWindowText);
			
			for(var i in smiley){
				$('<img />')
					.attr('src',   '/images/messenger/smilies/' + i + '.gif')
					.attr('alt',   smiley[i].text)
					.attr('title', smiley[i].text)
					.mousedown(function(ev) {
						ev.stopPropagation();
					})
					.click(function(smiley) {
							return function(){
								//alert(uiChatWindowTextarea.val())
								uiChatWindowTextarea.val(
									uiChatWindowTextarea.val() + ' ' + smiley.text + ' '
								);
							};
						}(smiley[i]))
					.appendTo(uiChatSmileyBlock);
			}
				
			
			(options.resizable && $.fn.resizable && this._makeResizable('se'));
			
			this.rawContacts        = null;
			this.current_message_id = false;
			this.send_typing        = true;
			this.contacts           = {};
			this.messages           = {};
			this.conversations      = {};
			this.contacts_ajax      = null;
			this.messages_ajax      = null;
			this.timeout            = null;
			this.new_messages       = false;
			this.messages_counter   = {};
			this.page_title         = document.title;
			this.current_chat_id    = options.current_chat_id == 'null' ? null : options.current_chat_id;
			options.messages        = window["eval"]("(" + options.messages + ")");
			options.conversations   = window["eval"]("(" + options.conversations + ")");
			
			var from, 
				messages = options.messages;
			
			for(var i = 0; i < messages.length; i++){
				
				if(messages[i].from == options.id){
					from = messages[i].to.replace(/\/\w*/,'');
				}else{
					from = messages[i].from.replace(/\/\w*/,'');
				}
				time = new Date();
				time.setTime(messages[i].stamp * 1000);// - time.getTimezoneOffset() * 60 * 1000
				
				messages[i].stamp = time.getHoursAndMinutes();
				
				this._pushMessage(from, messages[i]);
			}
			
			if(options.online){
				if($.browser.msie && parseInt($.browser.version) == 7){
					setTimeout(function(){
						self._getContacts(options.user_id);
						self._getMessages(options.user_id);
					}, 1000);
				}else{
					self._getContacts(options.user_id);
					self._getMessages(options.user_id);
				}				
			}
			
			this._isOpen = false;
			
			(options.autoOpen && this.open());
					
		},
		
		_toggleStatus: function(online){
			if(online){
				this.uiOnlineOffline
					.removeClass('ui-state-focus')
					.removeClass('ui-state-hover');
							
				this.uiOnlineOfflineText
					.removeClass('online')
					.addClass('offline');
							
				this.options.online = false;
				this.title = this.options.offlineText;
							
				$.ajax({
					url:   this.options.statusURL,
					data:  {status: 'offline'},
					type:  'POST',
					async: false
				});
				
			}else if(!this.contacts_ajax && !this.messages_ajax){
				this.uiOnlineOffline.addClass('ui-state-focus');
							
				this.uiOnlineOfflineText
					.removeClass('offline')
					.addClass('online');
							
				this.options.online = true;
				this.title = this.options.onlineText;
				
				$.ajax({
					url:   this.options.statusURL,
					data:  {status: 'online'},
					type:  'POST',
					async: false
				});
				
				this._getContacts(this.options.user_id);
				this._getMessages(this.options.user_id);
			}
		},
		
		destroy: function() {
			this.uiMessenger.hide();
			this.element
				.unbind('.messenger')
				.removeData('messenger');
			
			this.uiMessenger.remove();
			
			(this.originalTitle && this.element.attr('title', this.originalTitle));
		},
		
		open: function() {
			if (this._isOpen) { 
				this.uiChatWindow.hide();
				this.close();
				return; 
			}
			
			var options = this.options,
			uiMessenger = this.uiMessenger
			uiChatWindow = this.uiChatWindow;
			
			this._size();
			uiMessenger.show(options.show);
			if(this.current_chat_id) uiChatWindow.show();
			this.moveToTop(true);
			
			// set focus to the first tabbable element in the content area or the first button
			// if there are no tabbable elements, set focus on the dialog itself
			$([])
				.add(uiMessenger.find('.ui-messenger-content :tabbable:first'))
				.add(uiMessenger.find('.ui-messenger-buttonpane :tabbable:first'))
				.add(uiMessenger)
				.filter(':first')
				.focus();
			
			this._trigger('open');
			this._isOpen = true;
			
			$.post(this.options.settingsURL, {
				autoOpen: true
			});
		},
		
		close: function(event) {
			var self = this;
			
			if (false === self._trigger('beforeclose', event)) {
				return;
			}
			
			self.uiMessenger.unbind('keypress.ui-messenger');
			
			(self.options.hide 
			 	? self.uiMessenger.hide(self.options.hide, function() {
					self._trigger('close', event);
				})
				: self.uiMessenger.hide() && self._trigger('close', event));
			
			self._isOpen = false;
			
			$.post(this.options.settingsURL, {
				autoOpen: false
			});
			self._removeConversation();
		},
		
		_sendTyping: function(send){
			this.send_typing = !send;
			if(this.options.online && this.current_message_id){
				$.post(this.options.typingURL, {
					msg_id:   this.current_message_id, 
					msg_from: this.current_chat_id,
					start:    send
				});
			}
		},
		
		_getContacts: function(id){
			var self = this;
			clearTimeout(this.timeout);
			if(this.options.online){
				this.contacts_ajax = $.ajax({
					   url:      this.options.contactsURL,
					   data:     {id:id},
					   type:     'POST',
					   dataType: 'json',
					   cache:    false,
					   success:  function(data, textStatus){
									self.contacts_ajax = null;
									if(data.status == 1){
										self.rawContacts = data.response.contacts;
										self._renderContactsList(data.response.contacts);
										self._renderNewMessage(data.response.message);
										
									}else if(data.status == 0){
										//alert(data.response);
									}
									if(self.options.online){
										self.timeout = setTimeout(function () {
											self._getContacts(self.options.user_id);
										}, self.options.timeout * 1000);
									}
								}
				});	
			}
			
		},
		
		_getMessages: function(id){
			var self = this;
			if(this.options.online){
				this.messages_ajax = $.ajax({
					   url:      this.options.messagesURL,
					   data:     {id:id},
					   type:     'POST',
					   dataType: 'json',
					   cache:    false,
					   success:  function(data, textStatus){
									self.messages_ajax = null;
									if(data.status == 1){
										self.rawContacts = data.response.contacts;
										self._renderContactsList(data.response.contacts);
										self._renderComposeEvent(data.response.composing);
										self._renderNewMessage(data.response.message);
										self._getMessages(id);
									}else if(data.status == 0){
										//alert(data.response.message);
									}
								}
				});
			}
			
		},
		
		_renderComposeEvent: function(composing){
			for(var i = 0; i < composing.length; i++){
				if(composing[i].from == this.current_chat_id){
					if(composing[i].start){
						this.uiChatWindowText.addClass('start-composing');
					}else{
						this.uiChatWindowText.removeClass('start-composing');
					}
				}
			}
			
		},
		
		_renderNewMessage: function(messages){
			var time, conversation, from, message = '';
			for(var i = 0; i < messages.length; i++){
				
				from = messages[i].from = messages[i].from.replace(/\/\w*/,'');
				
				this._addConversation(this.contacts[from]);
				
				conversation     = this.conversations[messages[i].from.replace(/\/\w*/,'')],
				from             = conversation.data('contact').jid,
				messages[i].name = conversation.data('contact').name;
				
				if(messages[i].stamp){
					time = new Date();
					time.setTime(messages[i].stamp * 1000);// - time.getTimezoneOffset() * 60 * 1000
				}else{
					time = new Date();
				}
				messages[i].stamp = time.getHoursAndMinutes();
				
				this._pushMessage(from, messages[i]);
				
				if(this.current_chat_id == from){
					$('.ui-messenger-contact').removeClass('current-chat');
					conversation.addClass('current-chat');
					message += this._renderMessage(messages[i]);
				}else{
					conversation.data('contact').newmessage = true;
					this.messages_counter[from] += 1;
					conversation.removeClass('current-chat');
					conversation.addClass('new-message');
				}
			}
			
			this.uiChatWindowInnerBody.append(message);
			this.uiChatWindowBody.scrollTop(this.uiChatWindowInnerBody.height());
			
			this._ring();
		},
		
		_ring: function(){
			var count = 0;
			for(var i in this.messages_counter){
				count += this.messages_counter[i];
			}
			if(count){
				document.title = this.options.newmessageText + ' (' + count + ') ' + this.page_title;
				$('#messenger_link').html(this.options.title + ' (' + count + ')');
				if(this.new_messages) {
					$('#messenger_link').blink();
					this.new_messages = false;
				}
				$(window).focus();
			}else if(!this.new_messages){
				document.title = this.page_title;
				$('#messenger_link')
						.stop(true)
						.html(this.options.title)
						.css({opacity: 1.0});
				this.new_messages = true;
			}
		},
		
		_pushMessage: function(from, message){
			if(typeof(this.messages[from]) == 'undefined'){
				this.messages[from] = [];
			}
			this.messages[from].push(message);
		},
		
		sortContacts: function(contacts){
			var result    = {},
				sortable  = [],
				sortorder = this.options.sortorder;
			for(var i in contacts){
				contacts[i].firstname = contacts[i].nameshort;
				contacts[i].lastname  = $.trim(contacts[i].name.replace(new RegExp(contacts[i].nameshort), ''));
				sortable.push({
					id:  i,
					FL:  contacts[i].firstname,
					LF:  contacts[i].lastname
				});
			}
			sortable.sort(function(a,b){
				if(a[sortorder] < b[sortorder]) return -1;
				if(a[sortorder] > b[sortorder]) return  1;
				return 0;
			});
			for(var i = 0; i < sortable.length; i++){
				result[sortable[i].id] = contacts[sortable[i].id];
			}
			return result;
		},
		
		_getProperName: function(contact){
			return (this.options.sortorder == 'FL') ?
						contact.firstname + ' ' + contact.lastname :
						contact.lastname  + ' ' + contact.firstname
		},
		
		_renderContactsList: function(){
			var self     = this,
				contacts = this.sortContacts(this.rawContacts);
			
			this.uiOnlineContent.html('');
			this.uiOfflineContent.html('');
			for(var i in contacts){
				var onlineBlock = (contacts[i].show == 'on') ? this.uiOnlineContent : this.uiOfflineContent,
					
					onlineSyle = (contacts[i].show == 'on') ? ' online':' offline',
					
					contactData = (this.contacts[i] ? this.contacts[i].data('contact') : {}),
					
					newMessageClass = ( this.contacts[i] && 
										this.contacts[i].data('contact') && 
										this.contacts[i].data('contact').newmessage ? ' new-message':''),
					
					name = this._getProperName(contacts[i]),
				    
					uiContact = $('<div></div>')
						.hide()
						.addClass('ui-messenger-contact' + newMessageClass + onlineSyle)
						.appendTo(onlineBlock)
						.data('contact',$.extend(contactData, contacts[i])),
						
					uiContactLink = $('<a href="' + this.options.userURL + contacts[i].username + '"/>')
						.attr('title', contacts[i].status ? contacts[i].status : '')
						.addClass('ui-messenger-contact-link')
						.mousedown(function(ev) {
							ev.stopPropagation();
						})
						.click(function(contact) {
							return function(){
								uiContact.hide();
								self._addConversation(contact, true);
								return false;
							};
						}(uiContact))
						.text(name)
						.appendTo(uiContact);
						
				this.contacts[i] = $.extend(this.contacts[i] || {}, uiContact);
				
				if($.inArray( contacts[i].jid, this.options.conversations) != -1){
					if(!this._isOpen) this.open();
					this._addConversation(this.contacts[i], this.current_chat_id == contacts[i].jid);
				}
				
				if(this.conversations[i]){
					if(contacts[i].show == 'off'){
						this.conversations[i].removeClass('online');
						this.conversations[i].addClass('offline');
					}else{
						this.conversations[i].removeClass('offline');
						this.conversations[i].addClass('online');
					}
				}else{
					uiContact.show();
				}
			}
		},
		
		_removeConversation: function(){
			if(this.current_chat_id){
				this.contacts[this.current_chat_id].show();
				this.conversations[this.current_chat_id].remove();
				this.conversations[this.current_chat_id] = null;
				
				var temp = {};
				for(var i in this.conversations){
					if(this.conversations[i]) temp[i] = this.conversations[i];
				}
				this.conversations = temp;
				temp = [];
				
				for(var i = 0; i < this.options.conversations.length; i++){
					if(this.options.conversations[i] != this.current_chat_id){
						temp.push(this.options.conversations[i]);
					}else{
						//alert(this.surrent_chat_id)
					}
				}
				this.options.conversations = temp;
				
				this.uiChatWindow.hide();
				if(this.options.online){
					$.post(this.options.removeConURL, { jid: this.current_chat_id});
				}
				this.current_chat_id = null;
			}
		},
		
		_addConversation: function(contact, openChat){
			
			var self     = this,
				from     = contact.data('contact').jid,
				openChat = openChat || false;
			
			this.conversations[from] = {};
			this.messages_counter[from] = this.messages_counter[from] || 0;
			
			this.uiConversationsContent.html('');
			for(var i in this.conversations){
				if(this.contacts[i].data('contact')) {
				
				var contact = this.contacts[i].data('contact'),
					
					onlineSyle = (contact.show == 'on') ? ' online':' offline',
					newMessageClass = ( contact.newmessage ? ' new-message':'') + 
									  ( contact.currentchat ? ' current-chat':''),
					
					name = this._getProperName(contact),
				    
					uiContact = $('<div></div>')
						.show()
						.addClass('ui-messenger-contact' + newMessageClass + onlineSyle)
						.appendTo(this.uiConversationsContent)
						.data('contact', contact),
												
					uiContactLink = $('<a href="' + this.options.userURL + contact.username + '"/>')
						.attr('title', contact.status)
						.addClass('ui-messenger-conversation-link ' + onlineSyle)
						.mousedown(function(ev) {ev.stopPropagation();})
						.click(function(contact) {
							return function(){
								self._bindChatWindow(contact);
								
								return false;
							};
						}(i))
						.text(name)
						.appendTo(uiContact);
						
				this.conversations[i] = $.extend(this.conversations[i], uiContact);
				//alert(this.conversations[i].data('contact').count)
				}
			}
			
			if(openChat) this._bindChatWindow(from);
		},
		
		_bindChatWindow: function(from){
			uiChatWindow.show();
			var contact = this.conversations[from];
			
			contact.removeClass('new-message');
			
			$('.ui-messenger-contact').removeClass('current-chat');
			contact.addClass('current-chat');
			
			for(var i in this.contacts){
				if(this.contacts[i].data('contact')) {
					this.contacts[i].data('contact').currentchat = false;
				}
			}
			
			contact.data('contact').currentchat = true;
			
			if(this.messages_counter[from] > 0){
				contact.data('contact').newmessage  = false;
				this.messages_counter[from] = 0;
				
				this._ring();
			}
			
			var jid = contact.data('contact').jid,
				name = this._getProperName(contact.data('contact')),
				messages = this.messages[jid];
			this.current_chat_id = jid;
			uiChatWindowTitle.html(name);
			
			var message = '';
			
			for(var i in messages){
				message += this._renderMessage(messages[i]);
			}
			
			if(contact.data('contact').show == 'off'){
				message += this._offlineMessage(name);
			}
					
			this.uiChatWindowInnerBody.html(message);
			this.uiChatWindowBody.scrollTop(this.uiChatWindowInnerBody.height());
			$.post(this.options.settingsURL, {
				current_chat: jid
			});
		},
		
		_renderMessage: function(message){
			
			if(message.from == this.options.id){
				
				return '<tr><td class="my-message nobr" width="30">' + 
				       $.trim(this.options.nameshort) + '&nbsp;' + message.stamp + '</td><td class="my-message">' +
				       this._parseSmailey(message.body) + 
					   '</td></tr>';
			}else{
				this.current_message_id = message.id;
				this.uiChatWindowText.removeClass('start-composing');
				
				var contact = this.contacts[message.from].data('contact');
				return '<tr><td width="65">' + 
				       $.trim(contact.nameshort) + '&nbsp;' + message.stamp + '</td><td>' +
				       this._parseSmailey(message.body) + 
					   '</td></tr>';
			}
		},
		
		_offlineMessage: function(name){
			return '<tr><td colspan="2" class="my-message" style="color:#999999">' + 
						this.options.offlineMessage.replace(/\%\%/, name) + 
						'</td></tr>';
		},
		
		_parseSmailey: function(text){
			//text = text.htmlspecialchars_encode()
			for(var i in smiley){
				text = text.replace(smiley[i].regexp, '<img src="/images/messenger/smilies/' + i + '.gif" title="'+smiley[i].text+'" alt="'+smiley[i].text+'" />');
			}
			return text;
		},
		
		_sendMessage: function(){

			this.send_typing = true;
			var text = $.trim(uiChatWindowTextarea.val()).nl2br().autolink();
			
			if(text != ''){
				//if(this.options.online){
					var message = {
							from: this.options.id,
							to:   this.current_chat_id,
							name: this.options.name,
							body: text,
							stamp: new Date().getHoursAndMinutes()
						},
						
						contact = this.contacts[this.current_chat_id].data('contact'),
						
						messages = this._renderMessage(message);
					
					this.uiChatWindowInnerBody.append(messages);
					this.uiChatWindowBody.scrollTop(this.uiChatWindowInnerBody.height());
					
					this._pushMessage(this.current_chat_id, message);
					
					$.post(this.options.sendURL, {jid: this.current_chat_id, message: text});					
				//}
				uiChatWindowTextarea.val('');	
			}
			
		},
		
		_makeResizable: function(handles) {
			handles = (handles === undefined ? this.options.resizable : handles);
			var self = this,
				options = this.options,
				resizeHandles = typeof handles == 'string'
					? handles
					: 'n,e,s,w,se,sw,ne,nw';
			
			this.uiMessenger.resizable({
				cancel: '.ui-messenger-content',
				alsoResize: this.uiMessengerContent,
				maxWidth: options.maxWidth,
				maxHeight: options.maxHeight,
				minWidth: options.minWidth,
				minHeight: options.minHeight,
				start: function() {
					$(this).addClass("ui-messenger-resizing");
					(options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
				},
				resize: function(event, ui) {
					(options.resize && options.resize.apply(self.element[0], arguments));
					uiChatWindow.css({ left: ui.size.width + 10});
				},
				handles: resizeHandles,
				stop: function() {
					$(this).removeClass("ui-messenger-resizing");
					options.height = $(this).height();
					options.width = $(this).width();
					(options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
					$.post(options.settingsURL, {
						   width:      options.width,
						   height:     options.height
					});
				}
			})
			.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
			
			this.uiChatWindow.resizable({
				cancel: '.ui-chatwindow-content',
				alsoResize: '.ui-chatwindow-resize',
				maxWidth: options.maxChatWidth,
				maxHeight: options.maxChatHeight,
				minWidth: options.minChatWidth,
				minHeight: options.minChatHeight,
				start: function() {
					$(this).addClass("ui-chatwindow-resizing");
					(options.resizeStart && options.resizeStart.apply(self.element[0], arguments));
				},
				resize: function() {
					(options.resize && options.resize.apply(self.element[0], arguments));
					
				},
				handles: resizeHandles,
				stop: function() {
					$(this).removeClass("ui-chatwindow-resizing");
					options.chatHeight = $(this).height();
					options.chatWidth = $(this).width();
					(options.resizeStop && options.resizeStop.apply(self.element[0], arguments));
					self.uiChatWindowBody.scrollTop(self.uiChatWindowInnerBody.height());
					$.post(options.settingsURL, {
						   chatWidth:  options.chatWidth, 
						   chatHeight: options.chatHeight
					});
				}
			})
			.find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
		},
		
		_size: function() {
			/* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
			 * divs will both have width and height set, so we need to reset them
			 */
			var options = this.options;
			
			// reset content sizing
			this.uiMessengerContent.css({
				height: 0,
				minHeight: 0,
				width: 'auto'
			});
			
			this.uiChatWindowBody.css({
				height: 0,
				minHeight: 0,
				width: 'auto'
			});
			
			// reset wrapper sizing
			// determine the height of all the non-content elements
			var nonContentHeight = this.uiMessenger.css({
				height: 'auto',
				width: options.width
			})
			.height();
						
			this.uiMessengerContent
				.css({
					minHeight: Math.max(options.minHeight - nonContentHeight, 0),
					height: options.height == 'auto'
						? 'auto'
						: Math.max(options.height - nonContentHeight, 0)
				});
				
			var nonContentHeight = this.uiChatWindow.css({
				height: 'auto',
				width: options.chatWidth
			})
			.height();
			//alert(options.chatHeight)
			this.uiChatWindowBody
				.css({
					minHeight: Math.max(options.minChatHeight - nonContentHeight, 0),
					height: options.chatHeight == 'auto'
						? 'auto'
						: Math.max(options.chatHeight - nonContentHeight, 0)
				});
			
		},
		
		// the force parameter allows us to move modal dialogs to their correct
		// position on open
		moveToTop: function(force, event) {
			
			if (this.options.zIndex > $.ui.messenger.maxZ) {
				$.ui.messenger.maxZ = this.options.zIndex;
			}
			
			//Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
			//  http://ui.jquery.com/bugs/ticket/3193
			var saveScroll = { 
				scrollTop:  this.uiMessengerContent.attr('scrollTop'), 
				scrollLeft: this.uiMessengerContent.attr('scrollLeft') 
			};
			this.uiMessenger.css('z-index', ++$.ui.messenger.maxZ);
			this.uiMessengerContent.attr(saveScroll);
			this._trigger('focus', event);
		},
		
		isOpen: function() {
			return this._isOpen;
		},
		destroy: function() {
			$.widget.prototype.apply(this, arguments); // default destroy
			// now do other stuff particular to this widget
		}
	});
	
	$.extend($.ui.messenger, {
		version: "0.0.1",
		defaults: {
			user_id: 1,
			online: true,
			timeout: 120,
			autoOpen: false,
			sortorder: 'FL',
			closeOnEscape: true,
			closeText: 'close',
			conversationsText: 'Conversations',
			onlineText: 'Online',
			offlineText: 'Offline',
			offlineMessage: 'Offline',
			sendText: 'Send',
			smileyText: 'Smileys',
			sortText: 'Sort',
			messengerClass: '',
			chatWindowClass: '',
			hide: null,
			width: 150,
			height: 250,
			maxHeight: false,
			maxWidth:  300,
			minHeight: 150,
			minWidth:  150,
			chatWidth: 300,
			chatHeight: 'auto',
			maxChatHeight: 500,
			maxChatWidth: 500,
			minChatHeight: 200,
			minChatWidth: 300,
			resizable: true,
			show: null,
			stack: true,
			title: 'Messenger',
			zIndex: 1000,
			typingURL: '',
			contactsURL: '',
			messagesURL: ''
		},
	
		getter: 'isOpen',
	
		uuid: 0,
		maxZ: 0,
	
		getTitleId: function($el) {
			return 'ui-messenger-title-' + ($el.attr('id') || ++this.uuid);
		}
	});

})(jQuery);

(function($)
{
	$.fn.blink = function(options)
	{
		var defaults = { speed: 'fust', start: 1.0, end: 0 };
		var options = $.extend(defaults, options);
		
		return this.each(function(){
			$(this).css({display: 'block'});
			$.fn.doBlink($(this), options.speed, options.start, options.end);
		});
	}
	
	$.fn.doBlink = function(obj, speed, start, end){
		obj.animate({opacity: end}, speed);
		obj.animate({opacity: start}, speed);
		obj.queue(function () {
			$.fn.doBlink(obj, speed, start, end);
			$(this).dequeue();
		}); 
	}
	
})(jQuery);


