Array.extend({
	last: function() {
		return this[this.length - 1];
	}
});

Element.extend({
	getOffsets: function(noScroll){
		if (!noScroll) return this.getScrollOffsets();
		var el = this, offsetLeft = 0, offsetTop = 0;
		do {
			offsetLeft += el.offsetLeft;
			offsetTop += el.offsetTop;
		} while ((el = el.offsetParent));
		return {'x': offsetLeft, 'y': offsetTop};
	},

	getScrollOffsets: function(){
		var el = this, offsets = this.getOffsets(true);
		do {
			offsets.x += el.parentNode.scrollLeft || 0;
			offsets.y += el.parentNode.scrollTop || 0;
		} while ((el = el.parentNode));
		return {'x': offsetLeft, 'y': offsetTop};
	},

	getValue: function(){
		switch (this.getTag()){
			case 'select':
				if (this.type == 'select-one') {
					if (this.selectedIndex != -1) {
						var opt = this.options[this.selectedIndex];
						return opt.value || opt.text;
					}
					break;
				}
				var values = [];
				$each(this.options, function(opt) {
					if (opt.selected) values.push(opt.value || opt.text);
				});
				return values; break;
			case 'input': if (!(this.checked && ['checkbox', 'radio'].test(this.type)) && !['hidden', 'text', 'password'].test(this.type)) break;
			case 'textarea': return this.value;
		}
		return false;
	},

	calculateSize: function() {
			if (window.ie) return {'x': this.scrollWidth || this.offsetWidth, 'y': this.scrollHeight || this.offsetHeight};
			var retval = {};
			var values = {
					'x': ['width', 'padding-left', 'padding-right', 'margin-left', 'margin-right', 'border-left-width', 'border-right-width'],
					'y': ['height', 'padding-top', 'padding-bottom', 'margin-top', 'margin-bottom', 'border-top-width', 'border-bottom-width']};
			for (var i in values) {
					retval[i] = 0;
					values[i].each(function(attr) {
							var s = parseInt(this.getStyle(attr));
							if (s > 0) retval[i] += s;
					}, this);
			 };
			 return retval;
	},

	fixOverlay: function(hide) {
			if (!window.ie) return false;
			if (!this.fixOverlayElement) this.fixOverlayElement = new Element('iframe').setProperties({'frameborder': '0', 'scrolling': 'no', 'src': 'javascript:false;'}).setStyles({'position': 'absolute', 'border': 'none', 'filter': 'progid:DXImageTransform.Microsoft.Alpha(opacity=0)'}).injectAfter(this);
			if (hide) return this.fixOverlayElement.setStyle('display', 'none');
			var z = this.getStyle('z-index').toInt() || 0;
			if (z < 1) this.setStyle('z-index', (z = 2) );
			var pos = this.getPosition();
			this.fixOverlayElement.setStyles({'display' : '', 'z-index': z-1,
				'left': pos.left + 'px', 'top': pos.top + 'px',
				'width': pos.width + 'px', 'height': pos.height + 'px'});
			return this.fixOverlayElement;
	}
});

String.extend({
	sub: function(pattern, replacement){
		var result = '', source = this, match;
		if ($type(replacement) != 'function') replacement = function(match){ return new Template(replacement).parse(match); };
		while (source.length > 0){
			if (!(match = source.match(pattern))){
				result += source;
				break;
			}
			result += source.slice(0, match.index) + (replacement(match) || '').toString();
			source = source.slice(match.index + match[0].length);
		}
		return result;
	},

	toUnit: function(unit) {
		if (typeof unit == 'undefined') unit = 'px';
		return (this[(unit == 'px') ? 'toInt' : 'toFloat']() || 0) + unit;
	},

	parseQueries: function() {
		var vars = this.split(/[&;]/);
		var rs = {};
		if (vars.length) vars.each(function(val) {
			var keys = val.split('=');
			if (keys.length && keys.length == 2) rs[encodeURIComponent(keys[0])] = encodeURIComponent(keys[1]);
		});
		return rs;
	}
});

Number.prototype.toUnit = String.prototype.toUnit;

var Template = new Class({

	initialize: function(template, pattern) {
		this.template = template.toString();
		this.pattern  = pattern || Template.pattern;
	},

	parse: function(obj) {
		return this.template.sub(this.pattern, function(match) {
			return (match[1] == '\\') ? match[2] : (match[1] + (obj[match[3]] || '').toString());
		});
	}
});
Template.pattern = /(^|.|\r|\n)(\{\$(.*?)\})/;
