if (! Headwork) {
	var Headwork = {};
}
/**
 * Headwork
 */
Headwork = Object.extend(Headwork, {
	DEBUG: false,
	REGISTRY: {},
	WINDOWS: $A(),
	SCRIPTS: $A()
});

/**
 * Headwork.Modules
 *
 * @param {Object} modulename
 */
Headwork.Modules = {
	isLoaded: function(modulename) {
		return (Headwork.REGISTRY[modulename]);
	}
}

/**
 *
 * @param {String} namespace e.g 'NetworkService'
 */
Headwork.namespace = function(namespace, callback) {
	if (Object.isUndefined(Headwork[namespace])) {
		Headwork[namespace] = {};

		var script = new Element('script', {
			type: 'text/javascript',
			src: adminThemePath + '/js/headwork/' + String(namespace).toLowerCase() + '.js'
		});

		if (Prototype.Browser.IE) {
			script.observe('readystatechange', function() {
				if (script.readyState == 'loaded' || script.readyState == 'complete') {
					(callback || Prototype.emptyFunction)();
				}
			});
		} else {
			script.observe('load', function(e) {
				(callback || Prototype.emptyFunction)();
			});
		}

		document.getElementsByTagName('head')[0].appendChild(script);
		return;
	}
	(callback || Prototype.emptyFunction)();
}
/**
 * Headwork.Module
 *
 * @param {Object} name
 * @param {Object} object
 */
Headwork.Module = function(name, object) {
	var Base = {
		MODULENAME: name,

		options: {},
		lang: {},

		Model: {},
		View: {},

		init: Prototype.emptyFunction,
		close: Prototype.emptyFunction,
		Option: function(key, value) {
			if (Object.isUndefined(value)) {
				return this.options[key] || null;
			}
			return this.options[key] = value;
		}
	}

	object = Object.extend(Base, object);

	for (property in object) {
		if (Object.isFunction(object[property])) {
			object[property] = object[property].bind(object);
		}
	}

	window.Headwork[name.capitalize()] = object;
}

/**
 * Erzeugt neue Administratorenfenster
 *
 * @param {Object} onload
 * @param {Object} onclose
 * @param {Object} width
 * @param {Object} height
 * @param {Object} minheight
 * @param {Object} center
 * @param {Object} left
 * @param {Object} top
 * @param {Object} className
 * @param {Object} title
 */
Headwork.Window = Class.create({
	initialize: function(options) {
		this.id = 0;
		this.zIndex = 500;
		this.options = Object.extend({
			isModal: true,
			center: false,
			left: null,
			top: null,
			className: '',
			title: '',
			closeButton: true,
			name: '',
			autoFit: false
		}, options || { });

		this.render();
	},

	render: function() {
		var minheight = this.options.minheight ? this.options.minheight == 'auto' ? 'auto' : (this.options.minheight + "px") : '';
		var height = this.options.height ? this.options.height == 'auto' ? 'auto' : (this.options.height + "px") : '';
		var width = this.options.width ? this.options.width == 'auto' ? 'auto' : (this.options.width + "px") : '';

		this.wrapper = new Element('div', {
			'id': 'admin-window-' + (this.options.id || (this.id = Headwork.WINDOWS.length + 1)),
			'style': 'visibility:hidden'+
					 (height != '' ? ";height:" + height : '') +
					 (width != '' ? ";width:" + width : '') +
					 (minheight != '' ? ";min-height:" + minheight : '')
		});

		 // IE8 mag es nicht, wenn die Klasse oben direkt gesetzt wird
		this.wrapper.addClassName('admin admin-window' + (!this.options.className.empty() ? ' '+this.options.className : ''));

		this.wrapper.update(
			'<div class="admin-windowHeader"><span>' + this.options.title + '</span>' +
			'	<div class="admin-wait" style="display: none;"></div>' +
			(this.options.closeButton ? '<div class="admin-close" title="'+ langCommon['CLOSE'] +'"></div>' : '') +
			'</div>' +
			'<div class="admin-windowContent" id="admin-windowContent-' + this.id + '"></div>'
		);

		Element.extend(document.body).insert(this.wrapper);

		this.content = this.wrapper.down('div#admin-windowContent-' + this.id);

		this.options.onload = (this.options.onload || Prototype.emptyFunction).bind(this);
		this.options.onload();

		if(this.wrapper.down('div.admin-close')) {
			this.wrapper.down('div.admin-close').observe('click', (function(event) {
				(this.onClose || Prototype.emptyFunction)(event);
				(this._onClose)(event);
			}).bind(this));
		}

		this.handle = new Draggable(this.wrapper, {
			handle: this.wrapper.down('div.admin-windowHeader', 0),
			starteffect: function(){},
			endeffect: function(){}
		});

		// IE7: Breite der Leiste setzen, sonst zu klein. -2px wegen Border
		this.wrapper.down('.admin-windowHeader').setStyle({minWidth: this.wrapper.getWidth()-2+'px'});

		// Und mit der Toolbar hat er auch Probleme
		if (this.wrapper.down('.admin-toolbar')) {
			this.wrapper.down('.admin-toolbar').setStyle({minWidth: this.wrapper.getWidth()-2+'px'});
		}

		// Wenn der Titel laenger als das Fenster ist, muss das Fenster vergroessert werden
		var title = this.wrapper.down('.admin-windowHeader span');
		if (this.options.autoFit && title.getWidth() + 30 > this.content.getWidth()) {
			this.content.setStyle({minWidth: (title.getWidth() + 40) + 'px'});
		}

		if (this.options.center) {
			var viewportSize = document.viewport.getDimensions();
			var elementSize = this.wrapper.getDimensions();

			this.options.left = parseInt(this.options.left) || (viewportSize.width - elementSize.width) / 2;
			this.options.top  = parseInt(this.options.top) || (viewportSize.height - elementSize.height) / 2;

			this.options.left = this.options.left < 0 ? 30 : this.options.left;
			this.options.top  = this.options.top < 0 ? 30 : this.options.top;
		}

		this.wrapper.setStyle({left: this.options.left + 'px', top: this.options.top + 'px'});

		if (this.options.isModal) {
			if (Headwork.WINDOWS.size() > 0) {
				var lastWindow = Headwork.WINDOWS.last();
				this.zIndex = lastWindow.zIndex + 10;
			}
			$('adminModuleShatter').setStyle({'zIndex':this.zIndex});
			this.wrapper.setStyle({'zIndex':(this.zIndex+1)});
			$('admin_messages').setStyle({'zIndex':this.zIndex+1});

			if (Headwork.WINDOWS.size() == 0) {
				new Effect.Appear($('adminModuleShatter'), {
					from: 0,
					to: 0.3,
					duration: 0.5
				});
			}
		}

		this.wrapper.setStyle({'visibility':'visible'});
		Headwork.WINDOWS.push(this);

		if(popupForm = this.wrapper.down('form')) {
			if(popupForm.findFirstElement() && !popupForm.findFirstElement().disabled) {
				popupForm.focusFirstElement();
			}
		}
	},

	close: function() {
		this._onClose();
	},

	startWait: function() {
		this.wrapper.down('div.admin-wait').show();
		this.wrapper.addClassName('admin-progress');
	},

	stopWait: function() {
		this.wrapper.down('div.admin-wait').hide();
		this.wrapper.removeClassName('admin-progress');
	},

	destroy: function() {
		this._onClose();
	},

	_onClose: function() {
		this.options.onclose = (this.options.onclose || Prototype.emptyFunction).bind(this);
		this.options.onclose();

		var elementSize = this.wrapper.getDimensions();

		Headwork.WINDOWS = Headwork.WINDOWS.without(this);
		this.wrapper.remove();
		this.handle.destroy();

		var lastWindow = Headwork.WINDOWS.last();
		var	nextZIndex = Headwork.WINDOWS.size() > 0 ? lastWindow.zIndex : 0;

		$('admin_messages').setStyle({'zIndex':nextZIndex == 0 ? '99' : nextZIndex + 1});

		if(this.options.isModal && Headwork.WINDOWS.size() == 0) {
			new Effect.Fade($('adminModuleShatter'), {from: 0.3, to: 0, duration: 0.3, afterFinish: function(s) {
				$('adminModuleShatter').setStyle({'zIndex':nextZIndex});
			} });
		} else {
			$('adminModuleShatter').setStyle({'zIndex':nextZIndex});
		}
	}
});

Headwork.Window.close = function(name) {
	if (name.strip() == '') { return false; }
	$A(Headwork.WINDOWS).each(function(obj) {
		if (obj.options.name == name) {
			obj.close();
		}
	});
}


/**
 *
 * @param {Object} $super
 * @param {Object} options
 */
Headwork.Dialog = Class.create(Headwork.Window, {
	initialize: function($super, options) {
		var self = this, options = Object.extend({
			title: '',
			message: '',
			text: '',
			className: 'admin-dialog confirm',
			actions: [],
			appendCancel: true,
			autoFocus: false,
			autoSubmit: true,
			autoFormat: true,
			onload: Prototype.emptyFunction
		}, options || { });

		// Abbrechen-Button hinzufuegen
		if (options.appendCancel) {
			options.actions.push(new Headwork.Dialog.Button({
				text: langCommon['CANCEL'],
				className: 'admin-linkCancel'
			}));
		}

		if (options.autoFormat) {
			options.text = options.text.replace(/\\n/g, '<br />');
		}

		function _onLoad() {
			var dialog = this;

			// Inhalt einfuegen
			this.content.update(
				'<div class="innerSanctum"><h3>' + options.message + '</h3>'
				+ options.text
				+'</div><div class="admin-toolbar"><div class="admin-dialog-buttons"></div></div>'
			);

			$A(options.actions).each(function(button) {
				var buttonElement = button.getElement();
				if (Object.isFunction(button.options.callback)) {
					buttonElement.observe('click', function(e){
						if ((button.options.callback.bind(button))(e, dialog) !== false) {
							if(! button.options.stayOpen) {
								(dialog._onClose.bind(dialog))();
							}
						}
					});
				} else {
					buttonElement.observe('click', function(e) {
						if(! button.options.stayOpen) {
							(dialog._onClose.bind(dialog))();
						}
					});
				}
				dialog.content.down('div.admin-dialog-buttons').insert(buttonElement);
			});

			if (options.autoFocus) {
				var el = this.content.down('input,select,textarea', 0);
				if (el && el.focus) {
					new PeriodicalExecuter(function(pe) {
						if (el.visible()) {
							el.focus();
							pe.stop();
						}
					}, 0.2);
				}
			}

			if (options.autoSubmit && this.content.down('input[type="text"]', 0)) {
				this.content.down('input[type="text"]', 0).listen(function(e) {
					$A(options.actions).each(function(button) {
						if (button.options.autoSubmit && Object.isFunction(button.options.callback)) {
							if ((button.options.callback.bind(button))(e, dialog) !== false) {
								(dialog._onClose.bind(dialog))();
							}
						}
					});
				});
			}

			// Callback ausfuehren
			return (options.onload.bind(this))();
		}

		$super({
			isModal: true,
			center: true,
			closeButton: true,
			width:400,
			title: options.title,
			className: options.className,
			onload: _onLoad.bind(this)
		});
	}
});

Headwork.Dialog.Button = Class.create({
	initialize: function(options) {
		this.options = Object.extend({
			'className': '',
			'text': '',
			'returnValue': false,
			'autoSubmit': false,
			'callback': null,
			'stayOpen': false
		}, options || {});
	},
	getElement: function() {
		var button = new Element('a').addClassName('admin-link ' + this.options.className);
		return button.update(this.options.text);
	},
	fire: function() {
		return (this.options.callback.bind(this))();
	}
});

Headwork.ModuleWindow = Class.create(Headwork.Window, {
	initialize: function($super, module, transport, options) {
		var self = this, options = Object.extend({
			title: '',
			className: 'admin-window-' + module,
			onload: Prototype.emptyFunction,
			onclose: Prototype.emptyFunction
		}, options || { });

		self.scripts = $A();
		self.styles = $A();

		// Javascriptbloecke aktivieren
		var re = /<script.*?(?:src="(.*?)")?>([\s\S]*?)<\//ig;
		while (match = re.exec(transport.responseText)) {
			if (typeof match[1] != 'undefined') {
				self.scripts.push(new Element('script', {
					'type': 'text/javascript',
					'src': match[1]
				}));
			}
			if (typeof match[2] != 'undefined') {
				self.scripts.push(new Element('script', {'type': 'text/javascript'}).insert(match[2]));
			}
		}

		transport.responseText = transport.responseText.replace(/<script.*?(?:src="(.*?)")?>([\s\S]*?)<\/script>/ig, '');

		// CSS-Bloecke aktivieren (IE mag das nicht im Content)
		var re = /@import url\("(.*?)"\)/ig;
		while (match = re.exec(transport.responseText)) {
			self.scripts.push(new Element('link', {
				'type': 'text/css',
				'rel': 'stylesheet',
				'href': match[1]
			}));
		}

		var head = document.getElementsByTagName('head')[0];
		$A(self.scripts.concat(self.styles)).each(function(ref) {
			head.appendChild(ref);
		});

		function _onLoad() {
			// Inhalt einfuegen
			this.content.update(transport.responseText);
			this.content.select('style').invoke('remove');

			// Callback ausfuehren
			return (options.onload.bind(self))();
		}
		function _onClose() {
			$A(self.scripts.concat(self.styles)).each(function(ref) {
				ref.remove();
			});
			// Callback ausfuehren
			return (options.onclose.bind(self))();
		}

		$super({
			isModal: true,
			center: true,
			closeButton: true,
			title: options.title,
			className: options.className,
			autoFit: true,
			onload: _onLoad.bind(this),
			onclose: _onClose.bind(this)
		});
	}
});

// Namespace: Headwork.Widget
Headwork.Widget = {};

/**
 * Widget zur Suche von Gruppen.
 *
 * @param {Object} options
 */
Headwork.Widget.GroupSearch = Class.create({

	initialize: function(options, groups, messages) {

		var self = this;
		self.groups = $A();
		self.data = $H();
		self.messages = (messages || (lang || {}));

		self.options = Object.extend({
			'input': '.admin-groupSearch input[type="text"]',
			'select': '.admin-groupSearch select',
			'container': '.admin-groupSearchContainer',
			'search': '.admin-groupSearch a.admin-linkSearch',
			'add': '.admin-groupSearch a.admin-linkAddGroup',
			'elRemove': '.delete',
			'elName': '.groupname',
			'elId': 'input.groupid',
			'elRead': 'input.read',
			'elWrite': 'input.write',
			'elNotification': 'input.notification',
			'instantSearch': false, // Suche direkt beim Erzeugen des Widgets starten
			'onAdd': Prototype.emptyFunction,
			'onRemove': Prototype.emptyFunction,
			'onBeforeList': function(group) {return true;}, // Event, der vor dem Ausgeben der einzelnen Gruppen in der Suchergebnisliste ausgefuehrt wird
			'showWebGroup': false,
			'hideAdminGroups': false, // Gruppen mit dem Recht "allContents" nicht holen
			'hideRead': false,        // Lese- (und damit auch Schreib-)Checkboxen ausblenden
			'addEvenOdd': true,
			'roles': [],
			'wrapper': '',            // nur in Verbindung mit generateHtml = true notwendig (Gesamtcontainer, in dem das HTML landet
			'generateHtml': false     // bei true wird das ganze Konstrukt selbst erzeugt, bei false wird es als gegeben vorausgesetzt (abwaertskompatibel)
			                          // es wird dann im 'container' erzeugt
		}, options || { });

		if (self.options.generateHtml && ! messages) {
			new Ajax.Request(rootPath + '/modules/account/ajax/fetchTranslations.php', {
				method: 'get',
				parameters: { module: 'user', format: 'json'},
				onSuccess: (function(transport) {
					self.messages = transport.responseJSON;
					self.init(groups);
				})
			});
		} else {
			self.init(groups);
		}
	},

	init: function(groups) {

		var self = this;

		// HTML erzeugen
		if (self.options.generateHtml) {

			// Header
			var html = '<div class="admin-boxContent admin-groupSearchTop clearfix"><div class="admin-groupSearchBox clearfix">'+
					   '<input type="text" name="group" /><a class="admin-link admin-linkSearch">'+self.messages['SEARCH']+
					   '</a></div><div style="display:none" class="clearfix"><select multiple="multiple" size="5"></select>'+
					   '<a class="admin-link admin-linkAddGroup">'+self.messages['ADD_ASSIGN_GROUP']+'</a></div></div>';

			// Liste
			html += '<div class="admin-boxSub"><h3>'+self.messages['ASSIGNED_GROUPS']+
			        '</h3><form action="#" method="post" onsubmit="return false;" class="groupSearchWidgetForm">'+
			        '<table border="0" cellpadding="0" cellspacing="0" class="filter"><thead><tr><th>'+self.messages['GROUP']+'</th>';
			if(! self.options.hideRead) {
				html += '<th style="width:55px">'+self.messages['READ']+'</th><th style="width:55px">'+self.messages['WRITE']+'</th>';
			}
			html += '<th style="width:55px"></th></tr></thead></table><div style="max-height:300px;overflow-x:none;overflow-y:auto">'+
					'<table border="0" cellpadding="0" cellspacing="0" class="admin-accessTable"><tbody class="admin-groupSearchContainer"><tr style="display:none">'+
					'<td class="groupname"></td>';
			if(! self.options.hideRead) {
				html += '<td style="width:55px"><input type="checkbox" class="read" name="read[]" value="" /></td><td style="width:55px">'+
						'<input type="checkbox" class="write" name="write[]" value="" /></td>';
			}
			html += '<td style="width:40px"><input class="groupid" type="hidden" name="groupid[]" value="" />'+
			        '<img class="delete" src="'+adminThemePath+'/pics/icons/delete.png" alt="[x]" title="'+self.messages['REMOVE_COLUMN']+'" /></td></tr></tbody></table></div></form></div>';

			$$(self.options.wrapper)[0].update(html);
			self.options.input = self.options.wrapper + ' .admin-groupSearchTop input[type="text"]';
			self.options.select = self.options.wrapper + ' .admin-groupSearchTop select';
			self.options.search = self.options.wrapper + ' .admin-groupSearchTop a.admin-linkSearch';
			self.options.add = self.options.wrapper + ' .admin-groupSearchTop a.admin-linkAddGroup';
			self.options.container = self.options.wrapper + ' ' + self.options.container;

		}

		// Elemente initialisieren
		$A(['input', 'container', 'select', 'search', 'add']).each(function(property) {
			if (! Object.isElement(self.options[property]) && ! (self.options[property] = $$(self.options[property])[0])) {
				console.error('Invalid parameter "' + property + '".');
				throw new Error('Invalid parameter "' + property + '".');
			}
			self[property] = self.options[property];
		});

		var onSearch = Prototype.emptyFunction;

		self.input.listen(onSearch = function(event) {
			var element = self.input;
				element.value = element.value.strip().replace(/([^\d\w-_\s])+/g, '');
				self.lookup(element.value || '');
			Event.stop(event);
		});

		self.search.stopObserving('click');
		self.search.observe('click', onSearch);

		self.add.stopObserving('click');
		self.add.observe('click', function(event) {
			if(typeof $F(self.select) === 'object'){
				var groupsToAdd = $F(self.select);
			}
			else {
				groupsToAdd = new Array($F(self.select));
			}
			groupsToAdd.each(function(property) {
				var option = self.select.down('option[value~='+property+']');
				if (option && option.value && option.innerHTML != '') {
					self.addGroup({id: option.value, title: option.innerHTML, read: true, write: false, allContents: false});
					option.remove();
				}
				if (self.select.childElements().length == 0) {
					self.select.hide().up(0).hide();
				}
			});
		});

		self.sync();

		self.container.childElements().slice(1).each(function(entry) {
			var node = null;
			if (node = entry.down(self.options.elRemove, 0)) {
				node.observe('click', self.removeGroup.bind(self));
			}
		});

		if (groups) {
			for (var i = 0; i < groups.length; i++) {
				self.addGroup(groups[i]);
			}
		}

		if(self.options.instantSearch) {
			self.select.show().up(0).show();
			self.lookup(self.input.getValue());
		} else {
			self.select.hide().up(0).hide();
		}
	},

	getReadGroups: function() {
		var self = this;
		return self.container.select('input[type="checkbox"].read:checked:not(input:disabled)').pluck('value').without('');
	},

	getWriteGroups: function() {
		var self = this;
		return self.container.select('input[type="checkbox"].write:checked:not(input:disabled)').pluck('value').without('');
	},

	getGroups: function() {
		var self = this;
		return self.container.select('input[type="hidden"].groupid').pluck('value').without('');
	},

	lookup: function(groupName, options) {
		var self = this, groupName = String(groupName).strip(), messages = self.messages;
		var options = Object.extend({
			'text': groupName,
			'showAll': self.options.showAll,
			'showWarnings': true,
			'perPage': 500,
			'notIn': self.groups.join(','),
			'showWebGroup': (self.options.showWebGroup ? 1 : 0),
			'hideAdminGroups': (self.options.hideAdminGroups ? 1 : 0),
			'roles': self.options.roles.join(',')
		}, (options || {}));

		new Ajax.Request(rootPath + '/modules/user/ajax/getGroups.php', {
			method: 'get',
			parameters: options,
			onSuccess: (function(transport) {
				if (message = Ajax.isXMLError(transport, true)) {
					if (options['showWarnings']) {
						showMessage(messages[message] || message, true);
						return;
					}
				}

				var groups = $A(), list = transport.responseXML.getElementsByTagName('groups').item(0);
				if(list && list.childNodes.length > 0) {
					self.select.show().up(0).show();
					$A(list.childNodes).each(function(group) {

						var titles = {};
						$A(group.getElementsByTagName('title')).each(function(title) {
							titles[title.getAttribute('lang')] = title.firstChild.nodeValue;
						});

						var obj = {
							'id': parseInt(group.getAttribute('id')),
							'members': group.getAttribute('members'),
							'titles': titles
						};

						// je nach Return-Value die Ausgabe unterdruecken oder nicht
						if (! (self.options.onBeforeList.bind(this))(obj) ) {
							return;
						}

						groups.push(obj);
					});
				}

				if (groups.length == 0) {
					self.select.hide().up(0).hide();
				}

				(self.fillSelect.bind(this))(groups);
			}).bind(self)
		});
	},

	fillSelect: function(groups) {
		var self = this;
		self.select.update();
		groups.each(function(group) {
			self.select.insert(new Element('option', {
				'value': group.id
			}).update(group.titles[currentLanguage]));
		});
	},

	addGroup: function(group) {
		var self = this, template = self.container.down(0).template(), node;

		template.down(self.options.elName, 0).update(group.title);
		template.down(self.options.elId, 0).value = group.id;

		var templateRead = template.down(self.options.elRead, 0);
		var templateWrite = template.down(self.options.elWrite, 0);
		if (typeof(self.options.elNotification) != 'undefined') {
			var templateNotification = template.down(self.options.elNotification, 0);
		}

		self.groups.push(parseInt(group.id));
		self.data.set(group.id, {read: group.read || false, write: group.write || false});

		if(templateRead) {
			templateRead.checked = group.read;
			templateWrite.checked = group.write;
			templateRead.value = group.id;
			templateWrite.value = group.id;
			if (typeof(templateNotification) != 'undefined') {
				templateNotification.disabled = !group.read;
			}

			if(group.allContents) {
				templateRead.disable();
				templateWrite.disable();
				template.down(self.options.elRemove, 0).hide();

				self.data.get(group.id).write = true;
				self.data.get(group.id).read = true;
			} else {
				templateWrite.enable().observe('click', function(e) {
					self.data.get(this.value).write = ! this.checked;
					if (this.checked) {
						templateRead.checked = true;
						if (typeof(templateNotification) != 'undefined') {
							templateNotification.disabled = false;
						}
						self.data.get(this.value).read = true;
					}
				});
				templateRead.enable().observe('click', function(e) {
					self.data.get(this.value).read = ! this.checked;
					if (! this.checked) {
						templateWrite.checked = false;
						if (typeof(templateNotification) != 'undefined') {
							templateNotification.checked = false;
							templateNotification.disabled = true;
						}
						self.data.get(this.value).write = false;
					}
					else {
						if (typeof(templateNotification) != 'undefined') {
							templateNotification.disabled = false;
						}
					}
				});

				templateWrite[group.id == 0 ? 'hide' : 'show']();
				template.down(self.options.elRemove, 0).show();
			}
		}

		if (node = template.select(self.options.elRemove)[0]) {
			node.observe('click', self.removeGroup.bind(this));
		}

		self.container.insert(template.show());

		if (self.options['addEvenOdd']) {
			template.addClassName(template.previous(0).hasClassName('even') ? 'odd' : 'even');
		}

		(self.options['onAdd'].bind(self))(group, template);
	},

	sync: function() {
		var self = this, msg = '';

		self.groups = $A();
		self.data = $H();

		self.container.select(self.options.elId).each(function(input) {
			if (! input.value.empty()) {
				self.groups.push(parseInt(input.value))
			}
		});

		self.groups = self.groups.uniq();
		self.groups.each(function(id) {
			self.data.set(id, {read: false, write: false});
		});

		self.container.select(self.options.elRead).each(function(input) {
			if (! input.value.empty()) {
				self.data.get(input.value).read = input.checked;
			}
		});
		self.container.select(self.options.elWrite).each(function(input) {
			if (! input.value.empty()) {
				self.data.get(input.value).write = input.checked;
			}
		});
	},

	removeGroup: function(e) {
		var self = this; entry = (Object.isElement(e) ? e : e.element()), node = null;
		var ancestors = entry.ancestors(), index = ancestors.indexOf(self.container);
		var groupId = ancestors[index - 1].down(self.options.elId, 0).value;

		if (index !== -1 && Object.isElement(ancestors[index - 1])) {
			if (ancestors[index - 1].hasClassName('not-deleteable')) {
				return;
			}

			self.groups = self.groups.without(groupId);
			self.data.unset(groupId);

			ancestors[index - 1].remove();
		}

		(self.options['onRemove'].bind(self))(entry);

		self.lookup(self.input.getValue());
	}
});

Headwork.Widget.PageSearch = function(element, options) {
	var rootPath = window.rootPath || '';
	var self = {};
		self.element = $(element);
		self.options = Object.extend({
			'paramName': 'title',
			'type': [], // nur bestimmte Inhaltstypen
			'minChars': 2,
			'frequency': 0.2,
			'parameters': {},
			'searchContent' : false, // durchsucht Content statt Seiten
			'url': rootPath + '/modules/text/internalLinksAutoComplete.php',
			'afterUpdateElement': getSelectionId, // wenn dieses Option ueberschrieben wird, funktioniert darunterstehendes Verhalten nicht mehr (muss dann selbst gemacht werden)
			'target': self.element      // Feld, in dem die ID der Auswahl gespeichert werden soll. Wenn nichts angegeben, ist es das gleiche Feld (wird in hidden-Field umgewandelt)
		}, options || { });

	if (self.options.searchContent) {
		self.options.url = rootPath + '/modules/text/internalLinksAutoCompleteContent.php';
	}

	if (self.options.type) {
		self.options.parameters['type'] = self.options.type.join(',');
	}

	if (self.options.parameters) {
		self.options.parameters = Object.toQueryString(self.options.parameters);
	}

	if (self.options.target == self.element) { // gleiches Feld, Hidden-Fied erzeugen
		var mimicry = self.element.clone().writeAttribute('id', null);
		self.element.insert({before: mimicry});
		self.options.target = self.element.hide(); //writeAttribute('type', 'hidden');
		self.element = mimicry;
	}

	if ($F(self.options.target) != '') {
		self.options.searchContent ? getContentById($F(self.options.target)) : getPageById($F(self.options.target));
	}

	var results = new Element('div').addClassName('autocomplete');
	var Completer = new Ajax.Autocompleter(
			self.element,
			results,
			self.options.url,
			self.options);

	self.results = results;
	self.element.insert({after: results});

	Event.observe(results, "mouseover", Completer.onHover.bindAsEventListener(Completer));
	Event.observe(results, "click", Completer.onClick.bindAsEventListener(Completer));

	self.element.observe('keyup', function(e) {
		if($F(e.element()).empty()) {
			self.options.target.clear();
		}
	});

	self.options.target.observe('keyup', function(e) {
		if(!$F(e.element().empty())) {
			self.element.clear();
		}
	});

	// bbm start : fix fuer IE7-Fehler beim Autocomplete. Kann entfernt werden, wenn in scriptaculous (1.8.3) gefixt
	if (Prototype.Browser.IE) {
		results.observe('mousedown', ( function(e) {
			Completer.dontBlur = true;
			e.stop();
		}));
		results.observe('blur', ( function(e) {
			setTimeout(( function() {
				if (!$('linklisthref').focused)
					this.onBlur(e);
			}).bind(this), 100);
			e.stop();
		}).bindAsEventListener(Completer));

		self.element.observe('focus', function() {
			self.element.focused = true;
		});
		self.element.observe('blur', function() {
			self.element.focused = false;
		});
	} else {
		results.observe('mousedown', function(e) {
			e.stop();
		});
	}

	function getSelectionId(text, li) {
		self.options.target.value = li.id;
	}

	function getContentById(contentId) {
		if(!isNaN(contentId)) { // bei einer Nummer handelt es sich um einen internen Link
			new Ajax.Request(parent.rootPath + '/modules/browser/ajax/getContent.php', {
				method: 'get',
				parameters: {id: contentId},
				onComplete: function(transport) {
					var content = transport.responseJSON;
					self.element.value = content.title;
					self.options.afterUpdateElement(content.title, {id: contentId});
				}
			});
		}
	}

	function getPageById(pageId) {
		if(!isNaN(pageId)) { // bei einer Nummer handelt es sich um einen internen Link
			new Ajax.Request(parent.rootPath + '/modules/browser/ajax/getPagePosition.php', {
				method: 'get',
				parameters: {id: pageId},
				onComplete: function(transport) {
					var content = transport.responseJSON;
					if(content._title[parent.pageLanguage]) {
						self.element.value = content._title[parent.pageLanguage];
						self.options.afterUpdateElement(content._title[parent.pageLanguage], {id: pageId});
					}
				}
			});
		}
	}

	return self;
}

// Namespace: Headwork.Effect
Headwork.Effect = {};
Headwork.Effect.LoadingScreen = Class.create({
	initialize: function(element, options) {
		if(!$(element)) {
			return;
		}
		this.element = $(element);
		this.options = Object.extend({
			'className': '',
			'img': adminThemePath + '/pics/wait.gif',
			'text': 'Loading ...'
		}, options || { });

		var inner = new Template(
			'<img src="#{IMG}" alt="#{TEXT}" />' +
			'<p>#{TEXT}</p>'
		);
		this.loader  = new Element('div').addClassName('admin admin-loading ' + this.options.className).insert(inner.evaluate({
			'IMG':  this.options.img,
			'TEXT': this.options.text
		}));
		this.wrapper = new Element('div', {
			'style': 'visibility:hidden'
		});

		Element.wrap(this.element, this.wrapper);
		this.wrapper.insert({before: this.loader});
	},
	stop: function() {
		this.loader.remove();
		this.wrapper.setStyle({'visibility':'visible'});
		this.element.setStyle({'visibility':'visible'});
	}
});

Headwork.UIWidget = Class.create({
    listeners: {},
    isRendered: false,
    bind: function(event, handler) {
        if (! Object.isArray(this.listeners[event])) {
            this.listeners[event] = [];
        }
    },
    fire: function(event) {

    }
});

// Namespace: Headwork.BubbleManager
Headwork.BubbleManager = {
	bubbles: {},
	cursor: 1,
	close: function(bubble) {
		bubble = bubble.element ? $(Object.keys(Headwork.BubbleManager.bubbles).last()) : $(bubble);

		if (bubble && ! bubble.match('.admin-window.admin-bubble')) {
			bubble = bubble.up('.admin-window.admin-bubble');
		}
		if (Object.isUndefined(Headwork.BubbleManager.bubbles[bubble.id])) {
			return;
		}
    	if ($('adminBubbleShatter').visible()) {
    		$('adminBubbleShatter').hide();
    	}

    	var obj = Headwork.BubbleManager.bubbles[bubble.id];
			obj.content.childElements().each(function(child) {
				obj.parent.insert(child);
			});
    		obj.wrapper.remove()
	},
	repaint: function() {
		/*return console.log('resize');
		Object.keys(Headwork.BubbleManager.bubbles).each(function(k) {
			Headwork.BubbleManager.bubbles[k].repaint();
		});*/
	}
};

Event.observe(document.onresize ? document : window, "resize", Headwork.BubbleManager.repaint);

// Namespace: Headwork.Bubble
Headwork.Bubble = Class.create(Headwork.UIWidget, {
    initialize: function(target, options) {
        var self = this;
		this.options = Object.extend({
            stem: 'bottom',
            width: '250px',
            height: 'auto',
            modal: true,
            title: ''
        }, options);

        this.target = $(target);
        this.parent = null;

        this.id = 'bubble-' + Headwork.BubbleManager.cursor++;

        this.wrapper = new Element('div', {
            'id': this.id,
            'class': 'admin admin-window admin-bubble'
        });
        this.header  = new Element('div', {
            'class': 'admin-windowHeader'
        });
        this.content = new Element('div', {
            'class': 'admin-windowContent'
        });
        this.stem    = new Element('div', {
            'class': 'admin-bubbleStem'
        });

        this.header.insert('<div class="admin-close" title="'+ langCommon['CLOSE'] +'"></div>');
        this.header.down().observe('click', function() {
        	Headwork.BubbleManager.close(self.wrapper);
        });
        this.wrapper.addClassName('admin-bubbleStem' + this.options.stem.capitalize());
        this.wrapper.setStyle({width: this.options.width});

        Headwork.BubbleManager.bubbles[this.id] = this;
    },
    insert: function(content) {
    	this.parent = $(content).up(0);
    	this.content.insert($(content));
    },
    render: function(container) {
        this.wrapper.insert(this.header);
        this.wrapper.insert(this.content);
        this.wrapper.insert(this.stem);

        if (this.options.modal) {
        	if ($('adminBubbleShatter')) {
        		$('adminBubbleShatter').show();
        		$('adminBubbleShatter')
        			.stopObserving(Headwork.BubbleManager.close)
        			.observe('click', Headwork.BubbleManager.close);
        	}
        }

        container = $(container || document.body);
        container.insert(this.wrapper);

        this.repaint();

        this.isRendered = true;
    },
    repaint: function() {
    	// Calculate position
    	var position = this.target.viewportOffset();
    	var dimensions = this.target.getDimensions();
    	var offset = document.viewport.getScrollOffsets();

    	switch (this.options.stem) {
    		case "bottom":
    	    	var left = (position.left + (dimensions.width / 2 - (this.wrapper.getWidth() / 2)));
    	    	var top  = (position.top - this.wrapper.getHeight() - 10);
    	    	left = left <= 10 ? 10 : left;
    	    	top  = top <= 30 ? 30 : top;
    	    	break;
    		case "right":
    	    	var left = (position.left - this.wrapper.getWidth() - 10);
    	    	var top  = (position.top - 40);
    	    	break;
    	}

        this.wrapper.setStyle({
            'left': (left + offset.left) + 'px',
            'top': (top + offset.top) + 'px'
        });
    },
    close: function() {
    	Headwork.BubbleManager.close(this.wrapper);
    }
});

