/**
 * == MootoolsPatches ==
 * 
 * Extensions and patches to the mootools library.
**/

/**
 * String
 * 
 * String utility functions
 **/
String.implement({
	
	/**
	 * String.lcFirst -> String
	 * The string with the first character lowercased
	 **/
	lcFirst: function() {
		return this.substr(0, 1).toLowerCase() + this.substr(1);
	}
	
});

/**
 * JSON
 * 
 * Securety extensions regarding [js/json Hijecking](http://www.fortifysoftware.com/servlet/downloads/public/JavaScript_Hijacking.pdf)
 * Implementation ispired by, and compatible to Prototype.js default settings
 **/
JSON.extend({
	
	/**
	 * JSON.$jsonFilter -> RegExp
	 * The RegExp matching the "json secure filter", returning the "real json string" as match `$1`
	 **/
	$jsonFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

	/** section: MootoolsPatches
	 * the next two patches are regarding js/json Hijecking
	 * http://www.fortifysoftware.com/servlet/downloads/public/JavaScript_Hijacking.pdf
	 * Implementation ispired by, and compatible to Prototype.js default settings
	**/
	
	/**
	 * JSON.unFilter(text[, filter]) -> String
	 *     - text (`String`): The plain JSON-encoded text, either secured, or notü
	 *     - filter (`RegExp`): _(Optional)_ The filter matching the used secure string, returning the "real json string" as match `$1`
	 * 
	 * removes the securety filter (see [[JSON.$jsonFilter]]) from the passed text and retruns the trimmed version of that text
	 * 
	 * ##### Example
	 *      JSON.unFilter('\/*-secure-  {"foo":"bar"}  *\/')
	  * Returns the String
	  *     '{"foo":"bar"}'
	 **/
	unFilter: function (text, filter)
	{
		return text.replace(filter || this.$jsonFilter, '$1').trim();
	}
});

/**
 * class Request
 * Extensions made to the [Mootools Request](http://mootools.net/docs/core/Request/Request)
**/

/**
 * class Request.JSON
 * Extensions made to the [Mootools Request.JSON](http://mootools.net/docs/core/Request/Request.JSON)
 * 
 * ##### New Options
 * - `filter` (`Boolean`): _(Optional, default: `true`)_ whethe to [[JSON.unFilter]] the incomming JSON Response
 * - `jsonFilter` (`RegExp`): _(Optional, default: `JSON.$jsonFilter`)_ overwrites the used jsonFilter for that Request-Object
**/
Request.JSON.implement({

	options: {
		'filter': true,
		'jsonFilter': false
	},

	success: function (text)
	{
		if (true === this.options.filter) {
			text = JSON.unFilter(text, this.options.jsonFilter);
		}
		this.response.json = JSON.decode(text, this.options.secure);
		this.onSuccess(this.response.json, text);
	}
});

/**
 * class Array
 * Extentions to the native array
 **/
Array.implement({
	
	/** 
	 * Array.run([args, bind]) -> Array
	 *     - args (`Array`): _(Optional)_ An argument, or array of arguments to run the function with
	 *     - bind (`Object`): _(Optional)_ The object that the "this" of the function will refer to
	 * 
	 * Assumes, that all elements in this array are functions. Runns all function with given arguments and returns a new array containing all return values in same order.
	 * If an element is not a function, the element itself will be returned.
	 * 
	 * ##### Function
	 *     
	 *     fn(index, theArray[, arg1, arg2, ...])
	 *     
	 * - index (`Number`): The current item's index in the array
	 * - theArray (`Array`): The actual array.
	 * - argN (`mixed`): All the additonal arguments passed.
	**/
	run: function (args, bind) {
		var results = [];
		var args = $splat(args);
		for (var i = 0, l = this.length; i < l; i++) {
			
			results[i] = $lambda(this[i]).attempt(bind, [i, this].extend(args));
		}
		return results;
	}
});

/**
 * class Element
 * Extenstions to the [Mootools Native Element](http://mootools.net/docs/core/Element/Element)
**/

Element.implement({
	/**
	 * Element#slFetchEventUrl([defaultValue]) -> mixed
	 *     - defaultValue (mixed): the value, that shall be returned, when no url-value could be found
	 * 
	 * Fetched the href attribute of this element (if it is a link) or the next parent link element.
	 * 
	 * 
	 **/
	slFetchUrl: function (defaultValue) {
		if ('a' === this.get('tag')) {
			return this.get('href') || defaultValue;
		} else {
			el = this.getParent('a');
			if (el) {
				return el.get('href') || defaultValue;
			} else {
    			if ('form' === this.get('tag')) {
    				return this.get('action') || defaultValue;
                }
			}
		}
	}
});

