/*

Jappix - An open social platform
These are the seach tools JS script for Jappix

-------------------------------------------------

License: AGPL
Author: Vanaryon
Last revision: 19/03/11

*/

// Searches in the user's buddy list
function processBuddySearch(query) {
	// No query submitted?
	if(!query)
		return;
	
	// Wildcard (*) submitted
	if(query == '*')
		query = '';
	
	// Replace forbidden characters in regex
	query = escapeRegex(query);
	
	// Create an empty array
	var results = new Array();
	
	// Search regex
	var regex = new RegExp('((^)|( ))' + query, 'gi');
	
	// Search in the roster
	var buddies = getAllBuddies();
	
	for(i in buddies) {
		var xid = buddies[i];
		var nick = getBuddyName(xid);
		
		// Buddy match our search, and not yet in the array
		if(nick.match(regex) && !existArrayValue(results, xid))
			results.push(xid);
	}
	
	// Return the results array
	return results;
}

// Resets the buddy search tool
function resetBuddySearch(destination) {
	$(destination + ' ul').remove();
	$(destination + ' input').removeClass('suggested');
}

// Add the clicked XID to the input
function addBuddySearch(destination, xid) {
	// Remove the search tool
	resetBuddySearch(destination);
	
	// Define a selector
	var input = $(destination + ' input');
	var value = input.val();
	
	// Get the old value (if there's another value)
	var old = '';
	
	if(value.match(/(^(.+)(,)(\s)?)(\w+)$/))
		old = RegExp.$1;
	
	// Add the XID to the "to" input and focus on it
	$(document).oneTime(10, function() {
		input.val(old + xid).focus();
	});
	
	return false;
}

// Creates the appropriate markup for the search results
function createBuddySearch(destination) {
	// Reset the search engine
	resetBuddySearch(destination);
	
	// Get the entered value
	var value = $(destination + ' input').val();
	
	// Separation with a comma?
	if(value.match(/^(.+)((,)(\s)?)(\w+)$/))
		value = RegExp.$5;
	
	// Get the result array
	var entered = processBuddySearch(value);
	
	// Display each result (if any)
	if(entered && entered.length) {
		// Set a special class to the search input
		$(destination + ' input').addClass('suggested');
		
		// Append each found buddy in the container 
		var regex = new RegExp('((^)|( ))' + value, 'gi');
		
		// Initialize the code generation
		var code = '<ul>';
		
		for(b in entered) {
			// Get some values from the XID
			var current = getBuddyName(entered[b]).htmlEnc();
			current = current.replace(regex, '<b>$&</b>');
			
			// Add the current element to the global code
			code += '<li onclick="return addBuddySearch(\'' + encodeOnclick(destination) + '\', \'' + encodeOnclick(entered[b]) + '\');" data-xid="' + encodeQuotes(entered[b]) + '">' + current + '</li>';
		}
		
		// Finish the code generation
		code += '</ul>';
		
		// Creates the code in the DOM
		$(destination).append(code);
		
		// Put the hover on the first element
		$(destination + ' ul li:first').addClass('hovered');
		
		// Hover event, to not to remove this onblur and loose the click event
		$(destination + ' ul li').hover(function() {
			$(destination + ' ul li').removeClass('hovered');
			$(this).addClass('hovered');
			
			// Add a marker for the blur event
			$(destination + ' ul').attr('mouse-hover', 'true');
		}, function() {
			$(this).removeClass('hovered');
			
			// Remove the mouse over marker
			$(destination + ' ul').removeAttr('mouse-hover');
		});
	}
}

// Handles the keyboard arrows press when searching
function arrowsBuddySearch(e, destination) {
	// Down arrow: 40
	// Up arrown: 38
	
	// Initialize
	var code = e.keyCode;
	
	// Not the key we want here
	if((code != 40) && (code != 38))
		return;
	
	// Remove the eventual mouse hover marker
	$(destination + ' ul').removeAttr('mouse-hover');
	
	// Create the path & get its size
	var path = destination + ' ul li';
	var pSize = $(path).size();
	
	// Define the i value
	var i = 0;
	
	// Switching yet launched
	if(exists(path + '.hovered')) {
		var index = $(path).attr('data-hovered');
		
		if(index)
			i = parseInt(index);
		
		if(code == 40)
			i++;
		else
			i--;
	}
	
	else if(code == 38)
		i = pSize - 1;
	
	// We must not override the maximum i limit
	if(i >= pSize)
		i = 0;
	
	// We must not have negative i
	else if(i < 0)
		i = pSize - 1;
	
	// Modify the list
	$(path + '.hovered').removeClass('hovered');
	$(path).eq(i).addClass('hovered');
	
	// Store the i index
	$(path).attr('data-hovered', i);
	
	return false;
}

// Filters the buddies in the roster
var SEARCH_FILTERED = false;

function goFilterBuddySearch(vFilter) {
	// Put a marker
	SEARCH_FILTERED = true;
	
	// Show the buddies that match the search string
	var rFilter = processBuddySearch(vFilter);
	
	// Hide all the buddies
	$('#buddy-list .buddy').hide();
	
	// Only show the buddies which match the search
	for(i in rFilter) {
		// Choose the correct selector for this search
		if(!BLIST_ALL)
			$('#buddy-list .buddy[data-xid=' + escape(rFilter[i]) + ']:not(.hidden-buddy)').show();
		else
			$('#buddy-list .buddy[data-xid=' + escape(rFilter[i]) + ']').show();
	}
}

// Resets the buddy filtering in the roster
function resetFilterBuddySearch() {
	// Remove the marker
	SEARCH_FILTERED = false;
	
	// Show all the buddies
	$('#buddy-list .buddy').show();
	
	// Only show available buddies
	if(!BLIST_ALL)
		$('#buddy-list .buddy.hidden-buddy').hide();
	
	// Update the groups
	updateGroups();
}

// Funnels the buddy filtering
function funnelFilterBuddySearch(keycode) {
	// Get the input value
	var input = $('#buddy-list .filter input');
	var cancel = $('#buddy-list .filter a');
	var value = input.val();
	
	// Security: reset all the groups, empty or not, deployed or not
	$('#buddy-list .one-group, #buddy-list .group-buddies').show();
	$('#buddy-list .group span').text('-');
	
	// Nothing is entered, or escape pressed
	if(!value || (keycode == 27)) {
		if(keycode == 27)
			input.val('');
		
		resetFilterBuddySearch();
		cancel.hide();
	}
	
	// Process the filtering
	else {
		cancel.show();
		goFilterBuddySearch(value);
	}
	
	// Update the groups
	updateGroups();
}

// Searches for the nearest element (with a lower stamp than the current one)
function sortElementByStamp(stamp, element) {
	var array = new Array();
	var i = 0;
	var nearest = 0;
	
	// Add the stamp values to the array
	$(element).each(function() {
		var current_stamp = parseInt($(this).attr('data-stamp'));
		
		// Push it!
		array.push(current_stamp);
	});
	
	// Sort the array
	array.sort();
	
	// Get the nearest stamp value
	while(stamp > array[i]) {
		nearest = array[i];
		
		i++;
	}
	
	return nearest;
}