//
// This is meant to be a container of js functions of general purpose utility.
//
// It is included in theme.html so we can use them anywhere.
//

/// Encodes all arguments, concatenates them with slashes and prepends the base url if it is set
/// if the last argument is a dictionary, it is used to create a query string
function encodedURLFromComponents() {
	var url = BASE_URL;
	
	// defend against evil extra slashes that give mod_python so much trouble
	if ((/\/$/).test(url))
		url = url.slice(0,-1);
	
	for (var i = 0; i < arguments.length; i++)
		if (shouldEncodeParameterAsQueryString(i, arguments))
			url += encodedQueryParametersFromDict(arguments[i]);
		else
			url += '/' + encodeURIComponent(arguments[i]);
	
	return url;
	
	function shouldEncodeParameterAsQueryString(index, arguments) {
		var isLastArgument = index === arguments.length - 1;
		var isNotString = 'object' === typeof(arguments[index]);
		return isLastArgument && isNotString;
	}
}

function encodedQueryParametersFromDict(aDictionary) {
	var queryComponents = [];
	for (var key in aDictionary)
		queryComponents.push(encodeURIComponent(key) + '=' + encodeURIComponent(aDictionary[key]));
	
	if (0 === queryComponents.length)
		return '';
	
	return '?' + queryComponents.join('&');
}

/**
 Use this like someCallback.bind(this) to bind a specific this inside that callback.
 Especially usefull in jquery callbacks to retain an easy reference to the object 
 the callback was defined in. This should relieve us from having to do the 
 'var that = this;' dance most of the time.

 Here's an example usage:
 $('someSelector').click(function(){
 	this.doSomething();
 }.bind(this));
 */
Function.prototype.bind = function(thisReplacement) {
	var targetFunction = this;
	return function() {
		return targetFunction.apply(thisReplacement, arguments);
	};
};

// This monkey-patch provides me with method names in the debugger, instead of the always present 'anonymous'
// See http://dev.jquery.com/ticket/5275
(function() {
	var oldExtend = $.extend;
	
	function isSecondArgumentDictionary(arguments) {
		var methodDict = arguments[1];
		return (2 === arguments.length)
			&& (null !== methodDict || 'object' === typeof(methodDict));
	}
	
	function addMethodNamesOnMethodsInDict(methodDict) {
		for (var key in methodDict) {
			if ($.isFunction(methodDict[key]) 
				&& ! methodDict[key].displayName)
				methodDict[key].displayName = key;
		}
	}
	
	$.extend = function namingExtend() {
		if (isSecondArgumentDictionary(arguments))
			addMethodNamesOnMethodsInDict(arguments[1]);
		
		return oldExtend.apply(this, arguments);
	};
	
	// TODO: add tests for this and make it a patch to jquery proper
	
}());

function forceIERedraw(domOrJQuery) {
	if ( ! $.browser.msie)
		return;
	
	setTimeout(function(){
		$(domOrJQuery).toggleClass('force-ie-redraw').toggleClass('force-ie-redraw');
	}, 0);
}