(function() {

	SL.ui.Panel = Class.create(SL.Component, {
		init : function() {

			this.config.setDefault('position', 'bl');
			this.config.setDefault('as_tooltip', true);

			this.attachedElement = $(this.config.get('attach_id'));
			this.asTooltip = this.config.get('as_tooltip');

			this.trigger = $(this.config.get('mouse_over_id'));

			if (this.trigger) {
				this.trigger.observe('mouseenter', this.onMouseEnter.bind(this));
				this.trigger.observe('mouseleave', this.onMouseLeave.bind(this));
				this.e.observe('mouseenter', this.onMouseEnterOL.bind(this));
				this.e.observe('mouseleave', this.onMouseLeaveOL.bind(this));
			}

			if (this.config.get('expanded')) {
				this.toggle.bind(this).defer();
			}
		},

		notifyInitEvent : function(event) {
			if (this.trigger) {
				this.onMouseEnter(event);
			}
		},

		onMouseEnter : function(e) {
			this.mouseOnTrigger = true;
			if (!this.shown) {
				this.toggle();
			}
		},

		onMouseLeave : function(e) {
			this.mouseOnTrigger = false;
			if (this.mouseOnOverlay) {
				return;
			}
			if (this.hideTimeout) {
				clearTimeout(this.hideTimeout);
			}
			this.hideTimeout = setTimeout(this.hideDelayed.bind(this), 500);
		},

		onMouseEnterOL : function(e) {
			this.mouseOnOverlay = true;
		},

		onMouseLeaveOL : function(e) {
			this.mouseOnOverlay = false;
			if (this.mouseOnTrigger) {
				return;
			}
			if (this.hideTimeout) {
				clearTimeout(this.hideTimeout);
			}
			this.hideTimeout = setTimeout(this.hideDelayed.bind(this), 500);
		},

		hideDelayed : function() {
			if (!this.shown) {
				return;
			}
			if (!this.mouseOnTrigger && !this.mouseOnOverlay) {
				this.hide();
			}
		},

		toggle : function() {
			if (this.shown) {
				this.hide();
				return;
			}

			if (!this.initialized) {
				if (this.attachedElement) {
					this.ap = this.e.up('#admin_panel');
					if (!this.ap) {
						this.as = this.e.up('.gui_admin_sidebar_left_main');
						this.config.set('detach_to_body', true);
					}

					if (!this.ap && !this.config.get('detach_to_body')) {
						this.attachedElement.insert({
							after : this.e
						});

						this.attachedElement.up().setStyle({
							position : 'relative'
						});
					}

					if (this.config.get('overlay')) {
						this.e.absolutize();
						this.e.setStyle({
							width : null,
							height : null
						});
					}
				} else if (this.config.get('attach_id')) {
					console.log("Attached element not found", this.config.get('attach_id'));
				}
				this.initialized = true;
			}

			this.shown = true;

			if (this.attachedElement) {
				this.updatePosition();
			}

			this.e.show();

			if (this.asTooltip) {
				this.bodyCB = this.onBodyClicked.bind(this);

				(function() {
					// cb could already be removed here
					if (this.bodyCB) {
						$$('body')[0].observe('click', this.bodyCB);
					}
				}).bind(this).defer();

				SL.ui._registerActiveTooltip(this);
			} else {
				SL.ui._registerActiveTooltip(null);
				SL.ui._registerStaticTooltip(this);
			}

			if (this.attachedElement) {
				this.attachedElement.addClassName('active');
			}
		},

		onUpdate : function() {
		},

		onChildComponentChanged : function(component) {
			this.updatePosition(false);
		},

		updatePosition : function(first) {

			if (!this.shown) {
				return;
			}

			this.onUpdate();

			if (first && this.updateCB) {
				clearTimeout(this.updateCB);
			}

			if (this.config.get('detach_to_body') || this.ap) {
				if (!this.detached) {
					if (this.ap) {
						SL.utils.reparent(this.e, this.ap);
					} else {
						SL.utils.reparentToBody(this.e);
					}
					this.connectDestroy(this.attachedElement);
					this.detached = true;
				}

				var offset = this.attachedElement.cumulativeOffset();
				var topOffset = 0;

				var fixedElement = this.attachedElement.getFixedParent();
				var fixedScrollOffset;

				if (fixedElement) {
					fixedScrollOffset = this.attachedElement.cumulativeScrollOffsetFixed();
					offset.left -= fixedScrollOffset.left;
					offset.top -= fixedScrollOffset.top;
				}

				var parentScrollOffset = this.attachedElement.cumulativeScrollOffset();
				offset.left -= parentScrollOffset.left;
				offset.right -= parentScrollOffset.right;

				var scrollOffsets = document.viewport.getScrollOffsets();
				var viewDimensions = document.viewport.getDimensions();

				if (this.as || fixedElement) {
					topOffset = scrollOffsets.top;
				}

				var pos = this.config.get('position');

				if (pos == 'overlay') {

					var left = offset.left - 5;

					if (left + this.e.getWidth() > scrollOffsets.left + viewDimensions.width - 200) {
						left = offset.left + this.attachedElement.getWidth() - this.e.getWidth();
					}

					this.e.setStyle({
						top : (offset.top + topOffset - 5) + 'px',
						left : left + 'px',
						zIndex : this.getZIndex() + ''
					});
				} else {
					var top = offset.top + this.attachedElement.getHeight() + topOffset;

					if (fixedElement) {
						/*
						 * var elementTop = fixedElement.cumulativeOffset().top;
						 * var elementBottom =
						 * fixedElement.cumulativeOffset().top +
						 * fixedElement.getHeight();
						 * 
						 * if (top + this.e.getHeight() > elementBottom && top -
						 * this.e.getHeight() > elementTop) { top = top -
						 * this.e.getHeight(); }
						 */

						if (top + this.e.getHeight() > scrollOffsets.top + viewDimensions.height) {
							if (top - this.e.getHeight() > scrollOffsets.top) {
								top = top - this.e.getHeight() - this.attachedElement.getHeight();
							}
						}

					}

					if (pos == 'br') {
						this.e.setStyle({
							top : (top) + 'px',
							left : (offset.left + this.attachedElement.getWidth() - this.e.getWidth()) + 'px',
							zIndex : this.getZIndex() + ''
						});
					} else {
						this.e.setStyle({
							top : (top) + 'px',
							left : offset.left + 'px',
							zIndex : this.getZIndex() + ''
						});
					}
				}
			} else if (this.config.get('overlay')) {
				var offset = this.attachedElement.positionedOffset();

				var pos = this.config.get('position');

				if (pos == 'br') {
					this.e.setStyle({
						top : (offset.top + this.attachedElement.getHeight()) + 'px',
						left : (offset.left + this.attachedElement.getWidth() - this.e.getWidth()) + 'px',
						zIndex : this.getZIndex() + ''
					});
				} else {
					this.e.setStyle({
						top : (offset.top + this.attachedElement.getHeight()) + 'px',
						left : offset.left + 'px',
						zIndex : this.getZIndex() + ''
					});
				}
			}

			this.updateCB = setTimeout(this.updatePosition.bind(this), 250);
		},

		hide : function() {
			this._hide(false);
		},

		_hide : function(omitUnregister) {
			if (!this.shown) {
				return;
			}

			this.e.hide();
			this.shown = false;
			if (!omitUnregister) {
				if (this.asTooltip) {
					SL.ui._registerActiveTooltip(null);
				} else {
					SL.ui._registerStaticTooltip(null);
				}
			}
			if (this.bodyCB) {
				$$('body')[0].stopObserving('click', this.bodyCB);
				this.bodyCB = undefined;
			}

			if (this.attachedElement) {
				this.attachedElement.removeClassName('active');
			}
		},

		onBodyClicked : function(e) {
			if (this.shown) {

				var offset = this.e.cumulativeOffset();

				var x = e.pageX;
				var left = offset.left;
				var w = this.e.offsetWidth;
				var y = e.pageY;
				var top = offset.top;
				var h = this.e.offsetHeight;

				if (x > left && x < left + w && y > top && y < top + h) {
					return;
				}

				console.log(x, y, left, top, w, h);

				this.hide();
			}
		},

		getZIndex : function() {
			if (this.ap || this.config.get('admin')) {
				if (this.attachedElement && this.attachedElement.up('.admin_panel_toolbar')) {
					return 960;
				}
				return SL.admin._overlayIndex + 1;
			}
			return SL.ui._overlayIndex + 5;
		}
	});

})();

