(function(){
	var window = this,
		_keyev = window.keyev,
		_$e = window.$e,
		keyev = window.keyev = window.$e = function() {
			var res = new Array();
			for (var i = 0; i < arguments.length; i++) {
				res.push(keyev.fn.parse(arguments[i]));
			}
			return new keyev.fn.init(res);
		}
keyev.fn = keyev.prototype = {
	version: "0.0.1",
	started: 0,
	init: function (keys) {
		var res = this;
		res.keys = keys;
		return res;
	},
	oncharcode: {},
	bind: function (func) {
		if (!func) {
			return false;
		}
		if (this.started == 0) {
			keyev.start();
			keyev.fn.started = 1;
		}
		for (var key in this.keys) {
			var k = this.keys[key];
			if (typeof keyev.fn.oncharcode[k.key] == 'undefined') { 
				keyev.fn.oncharcode[k.key] = {};
			}
			if (typeof keyev.fn.oncharcode[k.key][k.act] == 'undefined') { 
				keyev.fn.oncharcode[k.key][k.act] = new Array();
			}
			keyev.fn.oncharcode[k.key][k.act].push({todo: func, alt: k.alt, ctrl: k.ctrl, shift: k.shift, meta: k.meta});
		}
		return true;
	},
	unbind: function (func) {
		for (var key in this.keys) {
			var k = this.keys[key];
			if (!(typeof keyev.fn.oncharcode[k.key] == 'undefined' || typeof keyev.fn.oncharcode[k.key][k.act] == 'undefined')) { 
				var todo = keyev.fn.oncharcode[k.key][k.act];
				for (i in todo) {
					if (todo[i].alt == k.alt && todo[i].ctrl == k.ctrl && todo[i].shift == k.shift && todo[i].meta == k.meta) {
						if (func) {
							if (todo[i].todo == func) {
								delete todo[i];
							}
						} else {
							delete todo[i];
						}
					}
				}
			}
		}
		return true;
	},
	modifiers: ["ctrl", "alt", "shift", "meta"],
	specialkeys: {"esc":27, "enter":13, "up":38, "down":40, "left":37, "right":39, "tab":9, "space":32, "pageup":33, "pagedown":34, "home":36, "end":35},
	actions: ["keyup", "keydown", "keypress"],
	event: function (e) {
		if (typeof event != 'undefined') {
			e = event;
		}
		var 
			alt = e.altKey ? 1 : 0,
			ctrl = e.ctrlKey ? 1 : 0,
			shift = e.shiftKey ? 1 : 0,
			meta = e.metaKey ? 1 : 0,
			key = e.keyCode;
			type = e.type;
		if (typeof keyev.fn.oncharcode[key] == 'undefined' || typeof keyev.fn.oncharcode[key][type] == 'undefined') {
			return;
		}
		var todo = keyev.fn.oncharcode[key][type];
		for (var i in todo) {
			if (todo[i].alt == alt && todo[i].ctrl == ctrl && todo[i].shift == shift && todo[i].meta == meta) {
				if (typeof todo[i].todo == 'string') {
					try {
						eval(todo[i].todo);
					} catch (ee) {
						return false;
					}
				} else if (typeof todo[i].todo == 'function') {
					var fu = todo[i].todo;
					try {
						fu(e);
					} catch (ee) {
						return false;
					}
				}
			}
		}
	}
}

keyev.fn.init.prototype = keyev.fn;

keyev.start = keyev.fn.start = function () {
	if (typeof Event.KEYUP != 'undefined') {
		document.captureEvents(Event.KEYUP, Event.KEYDOWN, Event.KEYPRESS);
	}
	document.onkeyup = keyev.fn.event;
	document.onkeydown = keyev.fn.event;
	document.onkeypress = keyev.fn.event;
	keyev.fn.started = 1;
}
keyev.stop = keyev.fn.stop = function () {
	document.releaseEvents(Event.KEYUP, Event.KEYDOWN, Event.KEYPRESS);
	keyev.fn.started = 0;
}
keyev.clear = keyev.fn.clear = function () {
	keyev.fn.oncharcode = {};
}
keyev.parse = keyev.fn.parse = function () {
	var res = {key: 0, alt: 0, ctrl: 0, shift:0, meta:0, act: "keyup"};
	var key = arguments[0] || "";
	key = key.replace(/\+/g, " ").toLowerCase().split(" ");
	for (i in key) {
		for (var j = 0; j < keyev.fn.modifiers.length; j++) {
			if (key[i] == keyev.fn.modifiers[j]) {
				res[key[i]] = 1;
			}
		}
		for (var j = 0; j < keyev.fn.actions.length; j++) {
			if (key[i] == keyev.fn.actions[j]) {
				res.act = key[i];
			}
		}
		for (var j in keyev.fn.specialkeys) {
			if (key[i] == j) {
				res.key = keyev.fn.specialkeys[j];
			}
		}
		if (key[i].length == 1 && key[i].match(/[a-zA-Z0-9]{1}/)) {
			res.key = key[i].toUpperCase().charCodeAt(0);
		} else if ((key[i].length == 2 || key[i].length == 3) && !isNaN(key[i]*1)) {
			res.key = key[i];
		}
	}
	return res;
}
})();
