/**
 * Prototype extensions
 * 
 * Function.inheritsFrom(parentClassObject)
 *
 * int pos		= Array.arrayPosition(needle)
 * bool result	= Array.inArray(needle)
 * array arr	= Array.copy()
 * array arr	= Array.fill(value, count)
 * array arr	= Array.map(function)
 * array arr	= Array.cAdd(array) - add coordinate pair
 * 
 * string str	= String.ltrim()
 * string str	= String.rtrim()
 * string str	= String.trim()
 * string str	= String.lpad()
 * string str	= String.rpad()
 * string str	= String.encode()
 * string str	= String.decode()
 * string str | date d	= String.toDateTime(locale, return as date object)
 * 
 * int days		= Date.getDaysOfMonth()
 * 
 * (c) Gregor Kofler, info@gregorkofler.at
 * @version 1.0.2 2007-06-04
 */
Function.prototype.inheritsFrom = function(parentClassOrObject){ 
	if(parentClassOrObject.constructor == Function) {
		//Normal Inheritance
		this.prototype				= new parentClassOrObject;
		this.prototype.parent		= parentClassOrObject.prototype;
		this.prototype.constructor	= this;
	}
	else { 
		//Pure Virtual Inheritance 
		this.prototype				= parentClassOrObject;
		this.prototype.parent		= parentClassOrObject;
		this.prototype.constructor	= this;
	} 
	return this;
}

Array.prototype.arrayPosition = function(needle) {
	for (var i = 0; i < this.length; i++) { if(this[i] == needle) { return i; }}
	return -1;
}

Array.prototype.inArray = function(needle) {
	for (var i = 0; i < this.length; i++) { if(this[i] == needle) { return true; }}
	return false;
}

Array.prototype.copy = function () { return ([].concat(this)); }

Array.prototype.fill = function(val, cnt) { for(var i = 0; i < cnt; i++) { this.push(val); }}

Array.prototype.map = function(f) {
	var i, r = [];
	for (i = 0; i < this.length; i++) { r.push(f(this[i]))};
	return r;
}

Array.prototype.cAdd = function(v) { return [parseInt(this[0])+parseInt(v[0]), parseInt(this[1])+parseInt(v[1])]; }
Array.prototype.cSub = function(v) { return [parseInt(this[0])-parseInt(v[0]), parseInt(this[1])-parseInt(v[1])]; }


String.prototype.ltrim = function() { return (this.replace(/^\s+/, "")); }
String.prototype.rtrim = function() { return (this.replace(/\s+$/, "")); }
String.prototype.trim = function() { return (this.replace(/^\s+\s+$/, "")); }

String.prototype.lpad = function(len, fillchar) {
	var i, pad = "";
	if(this.length >= len) { return this; }
	fillchar = fillchar || " ";
	for(i = 0; i < len-this.length; i++) { pad += fillchar; }
	return pad+this;
}
String.prototype.rpad = function(len, fillchar) {
	var i, pad = "";
	if(this.length >= len) { return this; }
	fillchar = fillchar || " ";
	for(i = 0; i < len-this.length; i++) { pad += fillchar; }
	return this+pad;
}

String.prototype.encode = function() {
	var i, result = "";
	for (i = 0; i < this.length; i++) { result += this.charAt(i) == " " ? "+" :	this.charAt(i); }
	return escape(result);
}

String.prototype.decode = function() { return unescape(this.replace(/\+/g, " ")); }

String.prototype.toDateTime = function(locale, asObj) {
	var del, erg, d, t, m, j;

	locale = locale || "date_de";

	switch (locale) {
		case "date_us":

		case "date_de":
			del = this.match(/\d{1,2}([-\/.])\d{1,2}\1\d{0,4}/);

			if(!del && (this.length == 4 || this.length == 6 || this.length == 8)) {
				erg = [this.substr(0,2), this.substr(2,2), this.substr(4)];
			}
			else if(del && del.length == 2) {
				erg = this.split(del[1]);
				if(erg.length != 3)			{ return false; }
			}
			else							{ return false; }

			d	= [
				"00".substring(0, 2-erg[0].length)+erg[0],
				"00".substring(0, 2-erg[1].length)+erg[1],
				new Date().getFullYear().toString().substring(0, 4-erg[2].length)+erg[2]
			];

			if(locale == "date_us") {
				t = parseInt(d[1], 10);
				m = parseInt(d[0], 10);
			}
			else {
				t = parseInt(d[0], 10);
				m = parseInt(d[1], 10);
			}
			j = parseInt(d[2], 10);

			if(m < 1 || m > 12)										{ return false; }
			if(t < 1 || t > new Date(j, m-1, 1).getDaysOfMonth())	{ return false; }

			if(asObj) { return new Date(j, m-1, t); }
			del = locale == "date_de" ? "." : "/";
			return d[0]+del+d[1]+del+d[2];
		
		case "date_iso":
			del = this.match(/\d{2}(\d{2})?([-\/.])\d{1,2}\2\d{1,2}/);

			if(!del && (this.length == 6 || this.length == 8)) {
				erg = [this.substr(0,this.length-4), this.substr(this.length-4,2), this.substr(this.length-2)];
			}
			else if(del && del.length == 3) {
				erg = this.split(del[2]);
				if(erg.length != 3)			{ return false; }
			}
			else							{ return false; }

			d	= [
				new Date().getFullYear().toString().substring(0, 4-erg[0].length)+erg[0],
				"00".substring(0, 2-erg[1].length)+erg[1],
				"00".substring(0, 2-erg[2].length)+erg[2],
			];

			j = parseInt(d[0], 10);
			m = parseInt(d[1], 10);
			t = parseInt(d[2], 10);

			if(m < 1 || m > 12)										{ return false; }
			if(t < 1 || t > new Date(j, m-1, 1).getDaysOfMonth())	{ return false; }

			if(asObj) { return new Date(j, m-1, t); }
			return d[0]+"-"+d[1]+"-"+d[2];

		case "time_hm":
			del = this.match(/\d{1,2}([-:.])\d{1,2}/);

			if(!del && this.length == 4) {
				erg = [this.substr(0,2), this.substr(2)];
			}
			else if(del && del.length == 2) {			
				erg = this.split(del[1]);
				if(erg.length != 2)	{ return false; }
			}
			else 					{ return false; }
			
			if(parseInt(erg[0], 10) > 23 || parseInt(erg[1], 10) > 59)
									{ return false; }
			return "00".substring(0, 2-erg[0].length)+erg[0]+":"+"00".substring(0, 2-erg[1].length)+erg[1];

		case "time_hms":
			del = this.match(/\d{1,2}([-:.])\d{1,2}\1\d{1,2}/);
			if(!del && (this.length == 6 || this.length == 4)) {
				erg = [this.substr(0,2), this.substr(2,2), this.substr(4)];
			}
			else if(del && del.length == 2) {			
				erg = this.split(del[1]);
				if(erg.length != 3)	{ return false; }
			}
			else 					{ return false; }

			h = parseInt(erg[0], 10);
			m = parseInt(erg[1], 10);
			s = parseInt(erg[2], 10);

			if(parseInt(erg[0], 10) > 23 || parseInt(erg[1], 10) > 59 || parseInt(erg[2], 10) > 59)
									{ return false; }
			return "00".substring(0, 2-erg[0].length)+erg[0]+":"+"00".substring(0, 2-erg[1].length)+erg[1]+":"+"00".substring(0, 2-erg[2].length)+erg[2];
	}
}

Date.prototype.getDaysOfMonth = function() {
	var d, m = this.getMonth(), y = this.getYear();
	y += y < 999 ? 1900 : 0;

	d = m == 3 || m == 5 || m == 8 || m == 10 ? 30 : 31;
	if(m == 1) { d -= y%4 == 0 && y%100 != 0 || y%400 == 0 ? 2 : 3; }
	return d;
}