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 ? 10 : this.options.left;
			this.options.top  = this.options.top < 0 ? 10 : 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) {
							(dialog._onClose.bind(dialog))();
						}
					});
				} else {
					buttonElement.observe('click', 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
		}, 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',
			'onAdd': undefined,
			'onRemove': undefined,
			'showWebGroup': false,
			'addEvenOdd': true,
			'roles': []
		}, options || { });

		// 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.select.hide().up(0).hide();
		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) {
			var option = Element.extend(self.select[self.select.selectedIndex]);
			if (option && option.value && option.innerHTML != '') {
				self.addGroup({id: option.value, title: option.innerHTML, read: false, 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]);
			}
		}
	},

	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),
			'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;
						});
						groups.push({
							'id': group.getAttribute('id'),
							'members': group.getAttribute('members'),
							'titles': titles
						})
					});
				} else {
					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);

		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(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;
						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;
						self.data.get(this.value).write = 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'] || Prototype.emptyFunction).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'] || Prototype.emptyFunction).bind(self))(entry);

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

Headwork.Widget.PageSearch = function(element, options) {
	var self = {};
		self.element = $(element);
		self.options = Object.extend({
			'paramName': 'title',
			'minChars': 2,
			'frequency': 0.2,
			'parameters': {}
		}, options || { });

	if (self.options.types) {
		self.options.parameters['type'] = self.options.types;
	}
	if (self.options.parameters) {
		self.options.parameters = Object.toQueryString(self.options.parameters);
	}

	var target = new Element('div').addClassName('autocomplete');
	var Completer = new Ajax.Autocompleter(self.element, target, rootPath + '/modules/text/internalLinksAutoComplete.php', self.options);

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

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

	target.observe('mousedown', function(e) {
		e.stop();
	});

	return self;
}

// Namespace: Headwork.Effect
Headwork.Effect = {};
Headwork.Effect.LoadingScreen = Class.create({
	initialize: function(element, options) {
		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'});
	}
});