// ARRAY COMPATIBILITY FUNCTIONS FOR JavaScript 1.6

(function(){

	var ap = Array.prototype;

	/**
	// create a new array with some items filtered out
	foo = [1,2,3,4,5];
	bar = foo.filter(function(x){return x%2==0;});
	// bar now equals [2,4]
	*/
	if (!ap.filter) {
		ap.filter = function(fun) {
			var len = this.length >>> 0;
			if (typeof fun != "function") { throw new TypeError(); }
			var res = new Array();
			var thisp = arguments[1];
			for (var i=0; i<len; i++) {
				if (i in this) {
					var val = this[i]; // in case fun mutates this
					if (fun.call(thisp, val, i, this)) { res.push(val); }
				}
			}
			return res;
		};
	}

	/**
	// runs a function against each item in array
	foo = ['potatoes','celery']
	foo.forEach(function(x){console.log("I like "+x);});
	// prints:
	// I like potatoes
	// I like celery
	*/
	if (!ap.forEach) {
		ap.forEach = function(fun) {
			var len = this.length >>> 0;
			if (typeof fun != "function") { throw new TypeError(); }
			var thisp = arguments[1];
			for (var i=0; i<len; i++) {
				if (i in this) { fun.call(thisp, this[i], i, this); }
			}
		};
	}

	/**
	// does the given function return true for every item in the array?
	foo = [4,8,6,1]
	function isEven(x){return x%2==0;}
	allEven = foo.every(isEven);
	// allEven is false
	*/
	if (!ap.every) {
		ap.every = function(fun) {
			var len = this.length >>> 0;
			if (typeof fun != "function") { throw new TypeError(); }
			var thisp = arguments[1];
			for (var i=0; i<len; i++) {
				if (i in this && !fun.call(thisp, this[i], i, this)) { return false; }
			}
			return true;
		};
	}

	/**
	// create a new array based on this array
	foo = [1,2,3];
	bar = foo.map(function(x){return x+"";});
	// bar now equals ["1","2","3"]
	*/
	if (!ap.map) {
		ap.map = function(fun) {
			var len = this.length >>> 0;
			if (typeof fun != "function") { throw new TypeError(); }
			var res = new Array(len);
			var thisp = arguments[1];
			for (var i=0; i<len; i++) {
				if (i in this) { res[i] = fun.call(thisp, this[i], i, this); }
			}
			return res;
	  	};
	}

	/**
	// does the given function return true for at least one item in the array?
	foo = [4,8,6,1]
	function isOdd(x){return x%2==1;}
	someOdd = foo.some(isOdd);
	// someOdd is true
	*/
	if (!ap.some) {
		ap.some = function(fun) {
			var i = 0, len = this.length >>> 0;
			if (typeof fun != "function") { throw new TypeError(); }
			var thisp = arguments[1];
			for (; i<len; i++) {
				if (i in this && fun.call(thisp, this[i], i, this)) { return true; }
			}
			return false;
		};
	}

	/**
	// return, but do not remove, the last element of the array
	foo = [4,8,6,1]
	var last = foo.peek()
	// last is 1
	*/
	if (!ap.peek) {
		ap.peek = function() {
			return this.length?this[this.length-1]:undefined;
		};
	}

})();
