/*
 * ADOBE SYSTEMS INCORPORATED
 * Copyright 2007 Adobe Systems Incorporated
 * All Rights Reserved
 * 
 * NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the 
 * terms of the Adobe license agreement accompanying it. If you have received this file from a 
 * source other than Adobe, then your use, modification, or distribution of it requires the prior 
 * written permission of Adobe.
 */

// Copyright 2001-2005 Interakt Online. All rights reserved.

/* *
 * base classes extensions
 * */

/* *
fix ecma compliance
 * */
if (!Function.prototype.apply) {
	Function.prototype.apply = function (o,a) {
		var r;
		if(!o){ o = {}; } // in case func.apply(null, arguments).
		o.___apply=this;
		switch((a && a.length) || 0) {
			case 0: r = o.___apply(); break;
			case 1: r = o.___apply(a[0]); break;
			case 2: r = o.___apply(a[0],a[1]); break;
			case 3: r = o.___apply(a[0],a[1],a[2]); break;
			case 4: r = o.___apply(a[0],a[1],a[2],a[3]); break;
			case 5: r = o.___apply(a[0],a[1],a[2],a[3],a[4]); break;
			case 6: r = o.___apply(a[0],a[1],a[2],a[3],a[4],a[5]); break;
			default: 
				for(var i=0, s=""; i<a.length;i++){
					if(i!=0){ s += ","; }
					s += "a[" + i +"]";
				}
				r = eval("o.___apply(" + s + ")");
		}
		o.__apply = null;
		return r;
	}
};

if (!Function.prototype.call) {
	Function.prototype.call = function(o) {
		// copy arguments and use apply
		var args = new Array(arguments.length - 1);
		for(var i=1;i<arguments.length;i++){
			args[i - 1] = arguments[i];
		}
		return this.apply(o, args);
	}
};

Function_bind = function(_this, object) {
	var __method = _this;
	return function() {
		__method.apply(object, arguments);
	}
};

Function_bindEventListener = function(_this, object) {
	var __method = _this;
	return function(event) {
		__method.call(object, event || window.event);
	}
};

if (!Array.prototype.push) {
	Array_push = function(_this, obj) {
		for (var i=1; i<arguments.length; i++) {
			_this[_this.length] = arguments[i];
		}
		return _this.length;
	}
} else {
	Array_push = function(_this, obj) {
		for (var i=1; i< arguments.length; i++) {
			_this.push(arguments[i]);
		}
		return _this.length;
	}
};

if (!Array.prototype.pop) {
	Array_pop = function(_this) {
		if(_this.length == 0){ 
			try{
				return undefined; 
			} catch(e) {
				return null;
			}
		}
		return _this[_this.length--];
	}
} else {
	Array_pop = function(_this) {
		return _this.pop();
	}
};

if (!Array.prototype.shift) {
	Array_shift = function(_this) {
		_this.reverse();
		var lastv = Array_pop(_this);
		_this.reverse();
		return lastv;
	};
} else {
	Array_shift = function(_this) {
		return _this.shift();
	};
};
// this splice works differently than the one provided with browsers
// because it doesn't change the original array
if (!Array.prototype.splice) {
  Array_splice = function(_this, start, deleteCount) {
    var len = parseInt(_this.length);

    start = start ? parseInt(start) : 0;
    start = (start < 0) ? Math.max(start+len,0) : Math.min(len,start);

    deleteCount = deleteCount ? parseInt(deleteCount) : 0;
    deleteCount = Math.min(Math.max(parseInt(deleteCount),0), len);

    var deleted = _this.slice(start, start+deleteCount);

    var insertCount = Math.max(arguments.length - 1,1);
    // new len, 1 more than last destination index
    var new_len = _this.length + insertCount - deleteCount;
    var start_slide = start + insertCount;
    var nslide = len - start_slide; // (_this.length - deleteCount) - start
    // slide up
    for(var i=new_len - 1;i>=start_slide;--i){
		_this[i] = _this[i - nslide];
	}
    // copy inserted elements
    for(i=start;i<start+insertCount;++i){
		_this[i] = arguments[i-start+3];
	}
    return deleted;
  };
} else {
	Array_splice = function(_this, start, deleteCount) {
		var args = [];
		var s = '';
		for(var i=3; i<arguments.length; i++) {
			args[i-3] = arguments[i];
			s += ', ' + 'args['+(i-3)+']';
		}
		s = 'var ret = _this.splice(start, deleteCount' + s + ')';
		eval(s);
		return ret;
	};
};

/* Object extensions */
// .toArray
Object_toArray = function(_this, delim) {
	var result;
	if (typeof(delim) == 'undefined') {
		delim = ',';
	}
	switch(typeof(_this)) {
		case 'array':
			result = _this;
			break;
		case 'string':
			if (_this.indexOf(delim)) {
				result = _this.split(delim);
			} else {
				result.push(_this);
			}
			break;
		default:
			result.push(_this);
			break;
	}
};

Object_weave = function(_this, source) {
	for (property in source) {
		_this[property] = source[property];
	}
	return _this;
};

Object_weave_safe = function(_this, source) {
	for (property in source) {
		if (typeof _this[property] == 'undefined') {
			_this[property] = source[property];
		}
	}
	return _this;
};


/* Array extensions */
// .indexOf : behaves exactly as String#indexOf
Array_indexOf = function(_this, x) {
	for (var i=0; i<_this.length; i++) {
		if (_this[i] == x) {
			return i;
		}
	}
	return -1;
};
// .lastIndexOf : behaves exactly as String#lastIndexOf
Array_lastIndexOf = function(_this, x) {
	for (var i=_this.length-1; i>=0; i--) {
		if (_this[i] == x) {
			return i;
		}
	}
	return -1;
};

Array_last = function(_this) {
	if (_this.length > 0) {
		return _this[_this.length - 1];
	}
};


/* String extensions */
// .trim : trim whitespace at beginning and end of a string
String_trim = function(_this, str) {
	if (!str) str = _this;
	return str.replace(/^\s*/, "").replace(/\s*$/, "");
};

// .normalize_space : return string with extra whitespace removed
String_normalize_space = function(_this, str) {
	if (!str) str = _this;
	return String_trim(str).replace(/\s+/g, " ");
};

String_htmlencode = function(_this, str) {
	if (!str) str = _this;
	return str.replace(/\&/g, "&").replace(/\</g, "&lt;").replace(/\>/g, "&gt;").replace(/\"/g, "&quot;");
};

String_htmldecode = function(_this, str) {
	if (!str) str = _this;
	return str.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, "\"").replace(/&/g, "&");
};
/* from ruby.js */
Array_each = function(_this, block) {
	for (var index = 0; index < _this.length; ++index) {
		var item = _this[index];
		block(item, index)
	}
	return _this;
};

Number_times = function(_this, block) {
	for (var i = 0; i < _this; i++) block(i)
};
 
/* helpers */
// min for array, string and as function
//  [3, 2, 4].min() => 2
Array_min = function(_this) {
	if (_this.length == 0) return false;
	if (_this.length == 1) return _this[0];
	var min, me, val;
	min = 0;
	me = _this;
	Array_each(me, function(val, i) {
		if (val < me[min]) {
			min = i;
		}
	});
	return _this[min];
};

// "3,2,4".min() => 2
String_min = function(_this) {
	return Array_min(_this.split(','));
};

// min(3, 2, 4) => 2
function min() {
	//arguments.each = Array.prototype.each;
	var a = [];
	Array_each(arguments, function(val, i) {
		Array_push(a, val);
	});
	return Array_min(a);
};

// max for array, string and as function
//  [3, 2, 4].max() => 4
Array_max = function(_this) {
	if (_this.length == 0) return false;
	if (_this.length == 1) return _this[0];
	var max, me, val;
	max = 0;
	me = _this;
	Array_each(me, function(val, i) {
		if (val > me[max]) {
			max = i;
		}
	});
	return _this[max];
};

// "3,2,4".max() => 4
String_max = function(_this) {
	return Array_max(_this.split(','));
};

// max(3, 2, 4) => 4
function max() {
	//arguments.each = Array.prototype.each;
	var a = [];
	Array_each(arguments, function(val, i) {
		Array_push(a, val);
	});
	return Array_max(a);
};

