SL.events = {};

(function() {

	SL.events.pushKeyboardObserver = function(cb) {

		if (!SL.events._keyboardObservers) {
			SL.events._keyboardObservers = $A();

			SL.events._keyboard = {
				shift : false
			};

			document.observe('keydown', function(state, event) {
				var code = event.keyCode;

				if (code != Event.KEY_ESC && SL.events._checkForm()) {
					return;
				}

				if (code == 16) {
					if (!state.shift) {
						state.shift = true;
						for ( var i = SL.events._keyboardObservers.length - 1; i >= 0; i--) {
							o = SL.events._keyboardObservers[i];
							if (o.shiftdown) {
								if (o.shiftdown(state)) {
									event.stop();
									return;
								}
							}
							if (o.modal) {
								return;
							}
						}
					}
					return;
				}

				state.code = code;
				state.key = String.fromCharCode(code).toLowerCase();

				for ( var i = SL.events._keyboardObservers.length - 1; i >= 0; i--) {
					o = SL.events._keyboardObservers[i];
					if (o.keydown) {
						if (o.keydown(state)) {
							event.stop();
							return;
						}
					}
					if (o.modal) {
						return;
					}
				}

			}.curry(SL.events._keyboard));

			document.observe('keyup', function(state, event) {
				if (SL.events._checkForm()) {
					return;
				}
				var code = event.keyCode;

				if (code == 16) {
					state.shift = false;
					for ( var i = SL.events._keyboardObservers.length - 1; i >= 0; i--) {
						o = SL.events._keyboardObservers[i];
						if (o.shiftup) {
							if (o.shiftup(state)) {
								event.stop();
								return;
							}
						}
						if (o.modal) {
							return;
						}
					}
					return;
				}

				state.code = code;
				state.key = String.fromCharCode(code).toLowerCase();

				for ( var i = SL.events._keyboardObservers.length - 1; i >= 0; i--) {
					o = SL.events._keyboardObservers[i];
					if (o.keyup) {
						if (o.keyup(state)) {
							event.stop();
							return;
						}
						if (o.modal) {
							return;
						}
					}
				}

				state.code = undefined;
				state.key = undefined;

			}.curry(SL.events._keyboard));
		}

		SL.events._keyboardObservers.push(cb);

		return cb;
	};

	SL.events.removeKeyboardObserver = function(cb) {

		if (cb.modal) {
			var index = SL.events._keyboardObservers.indexOf(cb);
			if (index >= 0) {
				SL.events._keyboardObservers = SL.events._keyboardObservers.slice(0, index);
			}
		} else {
			SL.events._keyboardObservers = SL.events._keyboardObservers.without(cb);
		}
	};

	SL.events._checkForm = function() {
		var e = document.activeElement;
		if (!e) {
			return false;
		}

		var name = e.tagName.toLowerCase();
		if (name == 'body') {
			return false;
		}
		if (name == 'input' || e.up('form')) {
			return true;
		}

		return false;
	};

})();

