(function($) {
	$.fn.extend({
		friendSearch: function(options) {
			var user_arr_friend = new Array();
			var user_arr_friend_username = new Array();
			var user_friend_count = 0;
			var user_friend_searching = false;
			var user_direct_key = false;
			
			if(options.contentClass == null) {
				options.contentClass = '';
	  	}
			if(options.referenceOnly == null) {
				options.referenceOnly = false;
	  	}
			
			if(options.contentStyle == null) {
				options.contentStyle = '';
	  	}
			
			if(options.delimiter == null) {
		  	var user_delimiter = '@';
		  } else {
		  	var user_delimiter = options.delimiter;
		  }
			
			function getCursorPos(){
				var cursorPos;
				if (window.getSelection) {
					var selObj = window.getSelection();
					var selRange = selObj.getRangeAt(0);
					cursorPos = findNode(selObj.anchorNode.parentNode.childNodes, selObj.anchorNode) + selObj.anchorOffset;
					/* FIXME the following works wrong in Opera when the document is longer than 32767 chars */
					//alert(cursorPos);
					return cursorPos;
				}
				else 
					if (document.selection) {
						var range = document.selection.createRange();
						var bookmark = range.getBookmark();
						/* FIXME the following works wrong when the document is longer than 65535 chars */
						cursorPos = bookmark.charCodeAt(2) - 11; /* Undocumented function [3] */
						//alert(cursorPos);
						return cursorPos;
					}
			}
			
			function findNode(list, node){
				for (var i = 0; i < list.length; i++) {
					if (list[i] == node) {
						return i;
					}
				}
				return -1;
			}
			
			function get_name(body_string, initial){
				if (initial) {
					body_string = body_string.substr(0, getCursorPos());
				}
				//alert('_' + body_string + '_');
				var index = body_string.indexOf(user_delimiter);
				
				if(user_delimiter.length == 0) {
					return body_string;
				}else if(index != -1) {
					return get_name(body_string.substr(index + user_delimiter.length), false);
				}	else if(!initial) {
					return body_string;
				}
				return -1;
			}

			function strip_html(text){
				return strip_html_tags(text.replace(/(<([^>]+)>(.)+<\/([^>]+)>)/ig, '')).replace(/&nbsp;/g, '');
			}
			
			function strip_html_tags(text){
				return text.replace(/<([^>]+)>/ig, '').replace(/&nbsp;/g, '');
			}
			
			function strip_plaintext(){
				//return text.replace(/>(.)+/ig, '').replace(/&nbsp;/g, '');
			}
			
			function highlight_row(){
				$('.found_friend[rel=' + $(this).attr('rel') + '] > p.highlight').removeClass('highlight');
				$(this).addClass('highlight');
			}
			
			function search_friends(rel){
				if (rel) {
					var match = get_name(strip_html($('.friendsearch_content[rel=' + rel + ']').html()), true);
					if (match.length) {
						match = match.toLowerCase();
						
						$('.friendsearch_found[rel=' + rel + ']').html('');
						
						if (match.length) {
							var friend = match.toLowerCase();
							for (var j in user_arr_friend) {
								if ((user_arr_friend[j].name.toLowerCase().indexOf(friend) > -1) || (user_arr_friend[j].username.toLowerCase().indexOf(friend) > -1)) {
									$('.friendsearch_found[rel=' + rel + ']').prepend('<p rel="' + rel +'" data-pattern="' + user_delimiter + match + '" id="found_friend_' + j + '" class="found_friend">' + user_arr_friend[j].name + '</p>');
								}
							}
						}
					}
				}
			}
			
			function pick_friend(){
				var id = $(this)[0].id.split('_')[2];
				var rel = $(this).attr('rel');
				var target_text = $(this).attr('data-pattern');
				
				$('.friendsearch_content[rel=' + rel + ']').html($('.friendsearch_content[rel=' + rel + ']').html().replace(target_text, '<span id="friend_' + id + '" rel="' + user_arr_friend[id].username + ':' + user_arr_friend[id].name + '" contenteditable="false">' + user_arr_friend[id].name + '</span>'));
				$('.friendsearch_found[rel=' + rel + ']').html('');
			}
			
			function friend_fetch(){
				if (!user_friend_searching) {
					user_friend_searching = true;
					$.ajax({
						url: SITEROOT+'/default/user/get-friend-list?format=json',
						dataType: 'json',
						method: 'post',
						success: function(data){
							user_friend_count = data.details.data.count;
							user_arr_friend = data.details.data.friends;
							search_friends();
							user_friend_searching = false;
						}
					});
				}
			}
			
			$(this).each(function(){
				var rel = 'friendsearch_' + Math.floor(Math.random() * 1150);

				$(this).parents('form').attr('rel', rel).bind('submit', function() {
					$('.friendsearch_content[rel=' + $(this).attr('rel') + ']').html('');
					$('.friendsearch_translated[rel=' + $(this).attr('rel') + ']').val('');
				});
				
				// dirtiness for IE
				var clone = $(this)[0].cloneNode(false);
				clone.type = 'hidden';
				$(clone).attr('class', 'friendsearch_translated').attr('rel', rel);
				$(this).after($(clone));
				$(this).after('<div rel="' + rel + '" class="friendsearch_found"></div>');
				$(this).after('<div rel="' + rel + '" class="friendsearch_content ' + options.contentClass + '" style="' + options.contentStyle + '" contenteditable="true">' + $(this).val() + '</div>');
				
				$(this).remove();
				
				$('.friendsearch_found[rel=' + rel + '] > p').live('click', pick_friend);
				
				$('.friendsearch_found[rel=' + rel + '] > p').live('mouseover', highlight_row);
				
				if(options.referenceOnly) {
					$('.friendsearch_content[rel=' + rel + '] > p').live('blur', strip_plaintext);
				}
				
				$('.friendsearch_content[rel=' + rel + ']').keydown(function(e){
					user_direct_key = true;
					var rel = $(this).attr('rel');
					switch (e.keyCode) {
						case 38:
							if ($('.friendsearch_found[rel=' + rel + '] > p.highlight').length) {
								$('.friendsearch_found[rel=' + rel + '] > p.highlight').removeClass('highlight').prev().addClass('highlight');
							}
							else {
								$('.friendsearch_found[rel=' + rel + '] > p:last').addClass('highlight');
							}
							break;
						case 40:
							if ($('.friendsearch_found[rel=' + rel + '] > p.highlight').length) {
								$('.friendsearch_found[rel=' + rel + '] > p:first.highlight').removeClass('highlight').next().addClass('highlight');
							}
							else {
								$('.friendsearch_found[rel=' + rel + '] > p:first').addClass('highlight');
							}
							break;
						case 13:
							$('.friendsearch_found[rel=' + rel + '] > p.highlight').trigger('click');
							break;
						default:
							user_direct_key = false;
							return true;
					}
					return false;
				});
				
				$('.friendsearch_content[rel=' + rel + ']').keyup(function(e){
					var rel = $(this).attr('rel');
					if (!user_direct_key) {
						if (!user_friend_count) {
							friend_fetch(rel);
						}
						else {
							search_friends(rel);
						}
					}
					else {
						return false;
					}
					if(options.referenceOnly) {
						//$('.friendsearch_translated[rel=' + rel + ']').val($('.friendsearch_content[rel=' + rel + ']').html().replace(/<span id="friend_(\d+)" rel="(.+)" [^>]+>.+<\/[^>]+>/ig, '[$1:$2]'));
					} else {
						$('.friendsearch_translated[rel=' + rel + ']').val($('.friendsearch_content[rel=' + rel + ']').html().replace(/<span id="friend_(\d+)" rel="(.+)" [^>]+>.+?<\/[^>]+>/ig, '[$1:$2]'));
					}
				});
			});
		}
	});
})(jQuery);

