var maskedBox = Class.create();
maskedBox.prototype = {
	// N required numeric (ascii 48..57)
	// n optional numeric (ascii 32,48..57)
	// A required alphanumeric (ascii 48-57, 65-90, 97-112, 128-)
	// a optional alphanumeric (ascii 32,48-57, 65-90, 97-112, 128-)
	// B required alpha (ascii 65-90, 97-112, 128-)
	// b optional alpha (ascii 32,65-90, 97-112, 128-)
	// U required uppercase (ascii 65-90, 97-112, 128-)
	// u optional uppercase (ascii 32,65-90, 97-112, 128-)
	// L required lowercase (ascii 97-112, 128-)
	// l optional lowercase (ascii 32,97-112, 128-)
	// P printable (ascii 32-)
	// \ escape for mask characters
	initialize: function(_p_objname, _p_tb, _p_mask, _p_default) {
		this.__lastvalid = "";
		this.__maskedlen = 0;
		this.__cnumber = false;
		this.__cspace = false;
		this.__cletter = false;
		this.__cprintable = false;
		this.__cuppercase = false;
		this.__clowercase = false;
		this.__tb = _p_tb;
		this.__tb.setAttribute('onkeypress', "return " + _p_objname + '.maskKeyPress(event);');
		this.__tb.setAttribute('onchange',_p_objname + '.maskOnChange();');
		
		this.__mask = _p_mask;

		var __defaultvalue = "";
		for(__i = 0; __i < this.__mask.length; __i++) {
			if(this.__mask.charAt(__i) == "\\") {
				__i++;
				__defaultvalue += this.__mask.charAt(__i);
			} else 
				switch(this.__mask.charAt(__i)) {
					case "N":
					case "A":
						__defaultvalue += "0";
						break;
					case "n":
					case "a":
					case "b":
					case "l":
					case "u":
					case "P":
						__defaultvalue += " ";
						break;
					case "B":
					case "U":
						__defaultvalue += "A";
						break;
					case "L":
						__defaultvalue += "a";
						break;
					default:
						__defaultvalue += this.__mask.charAt(__i);
				}
		}
		this.__maskedlen = __defaultvalue.length;
		this.__tb.value = __defaultvalue;
		if(this.checkValid(_p_default))
			this.__tb.value = _p_default;
		this.__lastvalid = this.__tb.value;
	},

	checkChar: function(__charcode) {
		this.__cnumber = ((__charcode >= 48) && (__charcode <= 57));
		this.__cspace = (__charcode == 32);
		this.__cletter = (((__charcode >= 65) && (__charcode <= 90)) || 
			((__charcode >= 97) && (__charcode <= 122)) || 
			(__charcode >= 128));
		this.__cprintable = (__charcode >= 32);
		this.__cuppercase = ((__charcode >= 65) && (__charcode <= 90));
		this.__clowercase = ((__charcode >= 97) && (__charcode <= 122));
		return;
	},

	setValue: function(__stringtoset) {
		if(this.checkValid(__stringtoset))
			this.__tb.value = __stringtoset;
	},

	checkValid: function(__stringtocheck) {
		if(__stringtocheck == undefined) {
			if(this.__mask == "")
				return true;
			return false;
		}
		// if the length differs from mask, surely wrong
		if(__stringtocheck.length != this.__maskedlen)
			return false;
		var __mp = 0;
		var __maskchar = "";
		var __charmask = "";
		for(__i = 0; __i < __stringtocheck.length; __i++) {
			__maskchar = this.__mask.charAt(__mp);
			if(__maskchar == "\\") {
				__maskchar = "";
				__charmask = this.__mask.charAt(__mp);
				__mp++;
			}
			__charcode = __stringtocheck.charCodeAt(__i);
			this.checkChar(__charcode);
			switch(__maskchar) {
				case "N":
					if(!this.__cnumber)
						return false;
					break;
				case "n":
					if(!(this.__cnumber || this.__cspace))
						return false;
					break;
				case "A":
					if(!(this.__cnumber || this.__cletter))
						return false;
					break;
				case "a":
					if(!(this.__cnumber || this.__cletter || this.__cspace))
						return false;
					break;
				case "B":
					if(!(this.__cletter))
						return false;
					break;
				case "b":
					if(!(this.__cletter || this.__cspace))
						return false;
					break;
				case "L":
					if(!(this.__clowercase))
						return false;
					break;
				case "l":
					if(!(this.__clowercase || this.__cspace))
						return false;
					break;
				case "U":
					if(!(this.__cuppercase))
						return false;
					break;
				case "u":
					if(!(this.__cuppercase || this.__cspace))
						return false;
					break;
				case "P":
					if(!this.__cprintable)
						return false;
					break;
				default:
					if(__maskchar != "")
						__charmask = __maskchar;
					if(__maskchar.charCodeAt(0) != __charcode)
						return false;
			}
			__mp++;
		}
		return true;
	},

	maskOnChange: function(__tb) {
		if(!this.checkValid(this.__tb.value))
			this.__tb.value = __lastvalid;
	},

	isMaskedPos: function(__p) {
		if(__p >= this.__mask.length) return false;
		var __charmask = "";
		var ___p = __p;
		for(__i = 0; ___p >= 0; __i++) {
			__charmask = "";
			if(this.__mask.charAt(__i) == '\\') {
				__i++;
				__charmask = this.__mask.charAt(__i);
				__maskchar = "";
			} else {
				__maskchar = this.__mask.charAt(__i);
				switch(__maskchar) {
					case "N":
					case "n":
					case "A":
					case "a":
					case "B":
					case "b":
					case "L":
					case "l":
					case "U":
					case "u":
					case "P":
						break;
					default:
						__charmask = this.__mask.charAt(__i);
				}
			}
			___p--;
		}
		return (__charmask != "");
	},

	getMaskChar: function (__p) {
		if(__p >= this.__mask.length) return "";
		var __maskchar = "";
		var ___p = __p;
		for(__i = 0; ___p >= 0; __i++) {
			__maskchar = "";
			if(this.__mask.charAt(__i) == '\\') {
				__i++;
			} else {
				switch(this.__mask.charAt(__i)) {
					case "N":
					case "n":
					case "A":
					case "a":
					case "B":
					case "b":
					case "L":
					case "l":
					case "U":
					case "u":
					case "P":
						__maskchar = this.__mask.charAt(__i);
						break;
				}
			}
			___p--;
		}
		return __maskchar;
	},

	maskKeyPress: function(__e) {
		if(this.__mask == "") return true;
		__ss = this.__tb.selectionStart;
		__value = this.__tb.value;
		// maszk aktualis ertekenek kinyerese
		var __maskchar = this.getMaskChar(__ss);
		if(__e.charCode == 0) {
			// vezerlo gomb
			if(__e.keyCode == 8) {
				// backspace
				if(__ss == 0)
					return false;
				var __delpos = __ss - 1;
				while(this.isMaskedPos(__delpos)) {
					__delpos--;
					if(__delpos == 0)
						return false;
				}
				__maskchar = this.getMaskChar(__delpos);
				var __replacewith = " ";
				switch(__maskchar) {
					case "N":
					case "A":
						__replacewith = "0";
						break;
					case "B":
					case "U":
						__replacewith = "A";
						break;
					case "L":
						__replacewith = "a";
						break;
				}
				this.__tb.value = this.replaceCharAt(__value, __delpos, __replacewith.charCodeAt(0));
				this.__tb.selectionStart = __delpos;
				this.__tb.selectionEnd = __delpos;
				this.__lastvalid = this.__tb.value;
				return false;
			}
			if(__e.keyCode == 46) {
				// del
				if(__ss >= this.__maskedlen)
					return false;
				__delpos = __ss;
				while(this.isMaskedPos(__delpos)) {
					__delpos++;
					if(__ss >= this.__maskedlen)
						return false;
				}
				__maskchar = this.getMaskChar(__delpos);
				var __replacewith = " ";
				switch(__maskchar) {
					case "N":
					case "A":
						__replacewith = "0";
						break;
					case "B":
					case "U":
						__replacewith = "A";
						break;
					case "L":
						__replacewith = "a";
						break;
				}
				this.__tb.value = this.replaceCharAt(__value, __delpos, __replacewith.charCodeAt(0));
				__delpos++;
				while(this.isMaskedPos(__delpos)) {
					__delpos++;
				}
				this.__tb.selectionStart = __delpos;
				this.__tb.selectionEnd = __delpos;
				this.__lastvalid = this.__tb.value;
				return false;
			}
			this.__lastvalid = this.__tb.value;
			return true;
		}

		this.checkChar(__e.charCode);

		var __replaceit = false;
		var __cc = __e.charCode;
		switch(__maskchar) {
			case "N":
				__replaceit = this.__cnumber;
				break;
			case "n":
				__replaceit = (this.__cnumber || this.__cspace);
				break;
			case "A":
				__replaceit = (this.__cnumber || this.__cletter);
				break;
			case "a":
				__replaceit = (this.__cnumber || this.__cletter || this.__cspace);
				break;
			case "B":
				__replaceit = (this.__cletter);
				break;
			case "b":
				__replaceit = (this.__cletter || this.__cspace);
				break;
			case "L":
				if(this.__cuppercase) {
					__cc = String.fromCharCode(__cc).toLowerCase().charCodeAt(0);
					this.__clowercase = true;
				}
				__replaceit = (this.__clowercase);
				break;
			case "l":
				if(this.__cuppercase) {
					__cc = String.fromCharCode(__cc).toLowerCase().charCodeAt(0);
					this.__clowercase = true;
				}
				__replaceit = (this.__clowercase || this.__cspace);
				break;
			case "U":
				if(this.__clowercase) {
					__cc = String.fromCharCode(__cc).toUpperCase().charCodeAt(0);
					this.__cuppercase = true;
				}
				__replaceit = (this.__cuppercase);
				break;
			case "u":
				if(this.__clowercase) {
					__cc = String.fromCharCode(__cc).toUpperCase().charCodeAt(0);
					this.__cuppercase = true;
				}
				__replaceit = (this.__cuppercase || this.__cspace);
				break;
			case "P":
				__replaceit = this.__cprintable;
				break;
		}
		if(__replaceit) {
			this.__tb.value = this.replaceCharAt(__value, __ss, __cc);
		} else
			return false;
		__ss++;
		while(this.isMaskedPos(__ss)) {
			__ss++;
		}
		this.__tb.selectionStart = __ss;
		this.__tb.selectionEnd = __ss;
		
		this.__lastvalid = this.__tb.value;
		return false;
	},

	replaceCharAt: function (__replacein, __replacepos, __charcode) {
		if(__replacepos > __replacein.length)
			return __replacein;
		return __replacein.substr(0, __replacepos) + String.fromCharCode(__charcode) + __replacein.substr(__replacepos + 1, __replacein.length);
	}
}

