(function() {

	SL.ui.MenuHorizontal = Class.create(SL.Component, {

		init : function() {

			this.config.setDefault('hide_delay', 500);
			this.config.setDefault('show_effect', 'blind_down');
			this.config.setDefault('show_duration', 200);
			this.config.setDefault('hide_effect', 'fade');
			this.config.setDefault('hide_duration', 200);
			this.config.setDefault('css_prefix', 'dropdown_menu');
			this.config.setDefault('mode', 'normal');

			this.cssPrefix = this.config.get('css_prefix');

			if (this.config.get('mode') == 'normal') {
				this.initSubElements(true, this.e.down('ul'));
			} else {
				this.e.select('li.' + this.cssPrefix + '_horizontal').each(this.initElement.bind(this, true));
				this.e.select('li.' + this.cssPrefix).each(this.initElement.bind(this, false));
			}
		},

		initSubElements : function(horizontal, ul) {
			ul.childElements().each(function(e) {
				this.initElement(horizontal, e);
				var children = e.down(">div.children>ul");
				if (children && !children.up().hasClassName('custom_children')) {
					this.initSubElements(false, children);
				}
			}.bind(this));
		},

		initElement : function(horizontal, e) {

			if (horizontal && SL.browser.IE6) {
				// TODO: Test if items have fixed width
				e.down().setStyle({
					width : '1%'
				});
			}

			e.observe('mouseenter', this.onMouseEnter.bind(this, e));
			e.observe('mouseleave', this.onMouseLeave.bind(this, e));
		},

		onMouseEnter : function(e) {

			// find and close other visible submenu of the parent menu
			var parent = e.up();
			parent.childElements().each(this._resetChild.bind(this, e));

			var ddnav = this.config.get('mode') == 'normal' ? e.down('div.children') : e.down('div.' + this.cssPrefix);
			if (!ddnav) {
				// this element doesn't have submenues
				return;
			}

			if (ddnav.retrieve('visible')) {
				// reset status to disable delayed hides
				if (ddnav.retrieve('status') != 'visible') {
					ddnav.store('status', 'visible');
				}
				return;
			}

			ddnav.store('visible', true);

			if (!SL.effects.resetCurrent(ddnav)) {
				SL.effects.resetStyles(e);
				var effect = this.config.get('show_effect');
				if (effect == 'appear') {
					ddnav.hide();
					SL.effects.registerCurrent(Effect.Appear(ddnav, {
						duration : this.config.get('show_duration') / 1000.0
					}));
				} else if (effect == 'blind_down') {
					ddnav.hide();
					SL.effects.registerCurrent(Effect.BlindDown(ddnav, {
						duration : this.config.get('show_duration') / 1000.0
					}));
				}
			}

			e.addClassName('active');
			this._getNavItem(e).addClassName('active');

		},

		_resetChild : function(current, e) {
			if (current == e) {
				return;
			}

			var child = this.config.get('mode') == 'normal' ? e.down('div.children') : e.down('div.' + this.cssPrefix);
			if (child == null /* || !child.retrieve('visible') */) {
				return;
			}

			SL.effects.resetCurrent(child);
			SL.effects.resetStyles(child);

			child.store('visible', false);
			child.store('status', 'hidden');

			e.removeClassName('active');
			this._getNavItem(e).removeClassName('active');

			child.hide();

		},

		onMouseLeave : function(e) {
			var ddnav = this.config.get('mode') == 'normal' ? e.down('div.children') : e.down('div.' + this.cssPrefix);
			if (!ddnav) {
				return;
			}

			ddnav.store('status', 'delayed_hide');

			setTimeout(this.delayedHide.bind(this, e, ddnav), this.config.get('hide_delay'));
		},

		delayedHide : function(e, ddnav) {
			if (ddnav.retrieve('status') != 'delayed_hide') {
				return;
			}

			SL.effects.resetCurrent(ddnav);

			var effect = this.config.get('hide_effect');
			if (effect == 'blind_up') {
				SL.effects.registerCurrent(Effect.BlindUp(ddnav, {
					duration : this.config.get('hide_duration') / 1000.0,
					afterFinish : this._clearHover.bind(this, e)
				}));
			} else if (effect == 'fade') {
				SL.effects.registerCurrent(Effect.Fade(ddnav, {
					duration : this.config.get('hide_duration') / 1000.0,
					afterFinish : this._clearHover.bind(this, e)
				}));
			} else {
				e.removeClassName('hover');
			}

			ddnav.store('visible', false);
			ddnav.store('status', 'hidden');

		},

		_clearHover : function(e) {
			e.removeClassName('active');
			this._getNavItem(e).removeClassName('active');
		},

		_getNavItem : function(li) {
			return li.down();
		}

	});

	SL.ui.ContextMenu = Class.create(SL.ui.Panel, {

		init : function($super) {

			var mode = this.config.get('mode');
			var attachID = this.config.get('attach_id');

			if (mode == 'mouseover') {
				this.config.setDefault('mouse_over_id', attachID);
			}

			$super();

			if (mode == 'contextmenu') {
				$(attachID).observe('contextmenu', function(e) {
					this.toggle(this);
					e.stop();
				}.bind(this));
			} else if (mode == 'click') {
				$(attachID).observe('click', this.toggle.bind(this));
			}

			var clickElement = $(this.config.get('click_id'));
			if (clickElement) {
				clickElement.observe('contextmenu', function(e) {
					this.toggle(this);
					e.stop();
				}.bind(this));
				clickElement.observe('click', function(e) {
					this.toggle(this);
					e.stop();
				}.bind(this));
			}

			this.e.select('a').each(function(e) {
				e.observe('click', function() {
					this.hide();
				}.bind(this));
			}.bind(this));
		},

		getZIndex : function($super) {
			if (this.ap || this.config.get('admin')) {
				return 960;
			}
			return $super();
		}
	});

})();

