(function($) {

	$.widget("ui.bhLayer", {
	
	// options: provided by framework
	// element: provided by framework
		
		init: function() {
			this.posParent(this.getData('posParentSelector'));
			this.opener(this.getData('openerSelector'));
			this.closer(this.getData('closerSelector'));
			if(typeof(this.getData('modal') == 'object') && !$("#modalOverlay").length){
				$("body").append("<div id='modalOverlay'></div>");
			}
		/*	this.element.find(".close")
				.data("bhLayerClose", this.element)
				.click(function(e){	
					$(this).data("bhLayerClose").bhLayer("hide");
					e.stopPropagation();
				});*/
		},
		show: function(){
			this.element.triggerHandler("onBeforeShow");
			if(getStyle(this.getData("posParent")[0], "position") == "static"){
				this.getData("posParent").css("position","relative").data("origPos", "static");
			}
			if(this.getData("autoHide")){
				// openLayers          not ME          not my ancestors              not my decendants
				$(".openBhLayer").not(this.element).not(this.element.parents()).not(this.element.find("*")).bhLayer("autoHide");
			}
			if(this.getData("modal")){
				$("body").data("bhLayerModalClose", this.element)
					.bind("click.bhLayerModal", function(e){/*.not(this.opener()).not(this.element).not(this.element.find("*"))*/
						clickee = e.target;
						isInside = false;
						$(this).data("bhLayerModalClose").find("*").each(function(){
							if(this == clickee) isInside = true;
						});
						$(this).data("bhLayerModalClose").bhLayer("opener").find("*").each(function(){
							if(this == clickee) isInside = true;
						});
						if($(this).data("bhLayerModalClose").bhLayer("opener")[0] == clickee || $(this).data("bhLayerModalClose")[0] == clickee || isInside)return;	
						$(this).data("bhLayerModalClose").bhLayer("hide");
					}
				);
				if(typeof(this.getData("modal")) == "object"){
					modalSettings = {
						overlayStyle: {
						width:$('body').width(),
						height:$('body').height(),
						zIndex: '9000',
							position: ($.browser.msie && $.browser.version < 7)? "absolute" : "fixed",
						top: 0,
							left: 0,
							backgroundColor: "#FFF",
							opacity: 0.7
						},
						center: false,
						moveToBottom: false,
						disableOverlayClick: false
					}
					$.extend(true, modalSettings, this.getData("modal"));
					$("#modalOverlay").show().css(modalSettings.overlayStyle);
					if(modalSettings.center){
						if(modalSettings.moveToBottom){
							$("#modalOverlay").after(this.element);
						}
						this.element.css({
							top: (($(window).height() - this.element.height()) / 2) + "px", 
							left: (($(window).width() - this.element.width()) / 2) + "px",
							position: ($.browser.msie && $.browser.version < 7)? "absolute" : "fixed"
						});
						$(window).data("modalShown", this.element).unbind(".modalBinding").bind("resize.modalBinding", function(){
							$(this).data("modalShown").bhLayer("show");
						});
						if($.browser.msie && $.browser.version < 7){window.scrollTo(0,0);}
					}
					if(modalSettings.disableOverlayClick){
						$("#modalOverlay").bind("click.modalBinding",function(e){
							e.stopPropagation();
						});
					}
				}
			}
			this.element.addClass("openBhLayer");
			if(this.element.ani = this.getData("showAnimation")){
				this.element.ani();
			}else{
				this.element.show();
			}
			this.element.triggerHandler("onAfterShow");
		},
		hide: function(){
			this.element.triggerHandler("onBeforeHide");
			this.element.removeClass("openBhLayer");
			if(this.getData("posParent").data("origPos") == "static"){
				this.getData("posParent").css("position","static").removeData("origPos");
			}
			if(this.getData("modal")){
				$("body").unbind("click.bhLayerModal").removeData("bhLayerModalClose");
				if(typeof(this.getData("modal") == "object")){
					$("#modalOverlay").hide().unbind(".modalBinding");
					$(window).unbind(".modalBinding").removeData("modalShown");
				}
			}
			if(this.element.ani = this.getData("hideAnimation")){
				this.element.ani();
			}else{
				this.element.hide();
			}
			this.element.triggerHandler("onAfterHide");
		},
		autoHide: function(){
			if(this.getData("autoHideable"))
				this.hide();
		},
		opener: function(openerSelector){
			if(openerSelector === undefined) {// is getter
				return this.getData("opener");
			}
			// first unbind curent opener
			if(this.getData("opener") && this.getData("opener").data("bhLayerOpen")){
				this.getData("opener").unbind(".bhlOpen").removeData("bhLayerOpen");
			}
			if(typeof(openerSelector) == "string"){
				if(!sibLingSelectorTest.test(openerSelector)){
					this.setData("opener", openerSelector.length ? this.element.parents(openerSelector) : this.element.parent());
				}else{
					this.setData("opener", this.element.siblings(openerSelector.replace(/^sibling / , "")));
				}				
			}else{
					this.setData("opener", openerSelector);
			}
			if(this.getData("opener")){
				this.getData("opener")	
					.data("bhLayerOpen", this.element)
					.bind("click.bhlOpen",function(e){
						$(this).data("bhLayerOpen").bhLayer("show");
						
				});
						if(this.getData("hover")){
							this.getData("opener").bind("mouseenter.bhlOpen", function(){
								hover = $(this).data("bhLayerOpen").bhLayer("getHover");
								if(typeof(hover) == "boolean"){  
									$(this).data("bhLayerOpen").bhLayer("show");
								}else{
									tSet = $(this);
									t = setTimeout(delayedShow, hover);
								}
							}).bind("mouseleave.bhlOpen", function(){clearTimeout(t);});
						}
			}
			return this;
		},
		closer: function(childSelector){
			if(childSelector === undefined) {// is getter
				return this.getData("closerChild");
			}
			// first unbind curent closer
			if(this.getData("closerChild") && this.getData("closerChild").data("bhLayerClose")){
				this.getData("closerChild").unbind("click.bhlClose").removeData("bhLayerClose");
			}
			this.setData("closerChild", childSelector.length ? this.element.find( childSelector) : this.element.find(".close"));
			this.getData("closerChild")
				.data("bhLayerClose", this.element)
				.bind("click.bhlClose", function(e){	
					$(this).data("bhLayerClose").bhLayer("hide");
					e.stopPropagation();
				});
			return this;
		},
		posParent: function(parentSelector){
			if(parentSelector === undefined) {// is getter
				return this.getData("posParent");
			}
			this.setData("posParent", parentSelector.length ? this.element.parents( parentSelector) : this.element.parent());
			return this;
		},
		getHover: function(){
			return this.getData("hover");
		},
		
		
		log: function(msg) {
			if(window.console && console.log) { // firebug logger
				console.log(msg);
			}
		},
		destroy: function() {
			this.hide();
			this.opener(false);
			$.widget.prototype.apply(this, arguments); // default destroy
		}
	
	});
	
	$.extend($.ui.bhLayer, {
		version: "@VERSION",
		getter: "opener closer posParent getHover", //for methods that are getters, not chainables
		
		defaults: {
			openerSelector: "",
			closerSelector: "",
			posParentSelector: "",
			autoHideable: 1,
			autoHide: 1,
			modal: 0,
			hover: 0
		}
		
	});

})(jQuery);
function getStyle(oElm, strCssRule){
	var strValue = "";
	if(document.defaultView && document.defaultView.getComputedStyle){
		strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
	}
	else if(oElm.currentStyle){
		strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
			return p1.toUpperCase();
		});
		strValue = oElm.currentStyle[strCssRule];
	}
	return strValue;
}
var t;
var tSet
function delayedShow(){
	tSet.data("bhLayerOpen").bhLayer("show");
}
var sibLingSelectorTest = new RegExp("^sibling");
