(function($) {
	$.fn.wnSimpleDropdown = function(options) {

		var defaults = {
			collapsedPathClass: "menuCollapsed",
			openEvent: "mouseenter",
			closeEvent: "mouseleave",
			defaultLevelStyle: "horizontalBar",
			levelStyle: {"1": "horizontalBar"} // types: "horzintalBar", "verticalBar", "box"

		};
		var options = $.extend(defaults, options);
		var $menu;
		
		/**
		 * Dodaje odpowiednie CSS wymagane przez nasz plugin do dzialania
		 */
		var addCssMarkup = function($el) {
			$menu.addClass("wnSimpleDropdown");
		};
		
		
		/**
		 * Dodaje odpowiednie CSS dla wskazanego submenu.
		 * 
		 */
		var addSubmenuCssMarkup = function($submenu) {
			var displayMode = getLevelStyleType($submenu.data("level"));
			$("> li:not(.filler):last", $submenu).addClass("wsd-last");
			$("> li:not(.filler):nth(0)", $submenu).addClass("wsd-first");

			
			if(displayMode == "box") {
				var columnCount = $submenu.data("wsd-box-columnsCount");
				$("> li:not(.filler)", $submenu).css("width", (100/columnCount)+"%");
			}
			
		}
		
		/**
		 * Zwraca nazwę stylu dla przekazanego poziomu menu
		 */
		var getLevelStyleType = function(level) {
			if(typeof(options.levelStyle[level]) != undefined) {
				var data = options.levelStyle[level];

				if(data instanceof Object) {
					return data.type;
				}
					
			} else {
				return options.defaultLevelStyle;
			}
		}
		/**
		 * Oblicza pozycje submenu (przekazany jako $submenu) w oparciu o pozycje rodzica 
		 * - przekazanego jako $parent
		 * 
		 * zwraca obiekt: {x: X, y: Y}
		 */
		var calculateSubmenuPosition = function($parent, $submenu) {
			// uwaga - niech tu ci nie przyjdzie do glowy "optymalizacja"
			// w postaci zapamietywania obliczen - wymiary okna moga sie zmienic!
			var position = {"x": 0, "y": 0};

			var windowWidth = $(window).width();
			
			var parentPos = $parent.offset();
			var parentHeight = $parent.height();
			var parentWidth = $parent.width();
			var displayMode = getLevelStyleType($submenu.data("level"));
			
			
			if(displayMode == "horizontalBar") {
				position.y = parentHeight;
			
				var submenuDimensions = $submenu.data("wsd-dimensions");
				position.x = parseInt(-(submenuDimensions.width/2) + (10*submenuDimensions.width)/100);

				// zabezpieczenie przed wyjechaniem za ekran.
				// jezeli width + pozycja przekracza wymiary okna, to na sile przesuwamy menu w lewo
				var menuEndPosition = parentPos.left + submenuDimensions.width + position.x;
				if(menuEndPosition > windowWidth) {
					// wyjechalismy poza ekran - przesuwamy sie w lewo
					var diff = menuEndPosition - windowWidth;
					
					position.x -= diff;
				}
			} else if(displayMode == "box") {
				position.y = parentHeight;

				$submenu.css("visibility", "hidden").css("display", "block");
				var submenuOffset = $submenu.offset();
				$submenu.css("display", "none").css("visibility", "visible");
				
				var submenuDimensions = $submenu.data("wsd-dimensions");
					
				if(parentPos.left > submenuOffset.left) {
					position.x = -(submenuDimensions.width/2);
				}
			} else if(displayMode == "verticalBar") {
				position.y = parentHeight;
				
				var submenuDimensions = $submenu.data("wsd-dimensions");

				position.x = parentWidth/2 - submenuDimensions.width/2;
				
				
				// obliczamy szerokosc pozostalych elementow menu (z prawej)
				var parentMenuWidth = 0;
				$parent.add($parent.nextAll("li")).each(function() {
					parentMenuWidth += $(this).width();
				});
				
				var parentMenuPrevWidth = 0;
				$parent.prevAll("li").each(function() {
					parentMenuPrevWidth += $(this).width();
				});
				
				// jezeli wystajemy z lewej strony - sztucznie przesuwamy sie w prawo
				if(Math.abs(position.x) > parentMenuPrevWidth) {
					position.x = -parentMenuPrevWidth + 21; // 21 to haxior ;(
				}

				// obliczamy jaka jest faktyczna szerokosc submenu po przesunieciach
				var realSubmenuWidth = submenuDimensions.width + position.x; // (position.x jest ujemne!)
				
				if(parentMenuWidth < realSubmenuWidth) {
					if(getLevelStyleType($parent.data("level")) == "horizontalBar") {
						// jezeli wystajemy poza menu wyzszego levelu- przesuwamy sie
						position.x = position.x - (realSubmenuWidth - parentMenuWidth) - 21; // przesuwamy submenu w lewo o tyle o ile wystaje. 21 to haxior na filler
					}
				}
			}
			
			
			return position;
		};
	
		/**
		 * Oblicza wymiary dla submenu ktore zaraz bedzie otwierane
		 * 
		 * W zaleznosci od options.mode moga to byc rozne wymiary.
		 * 
		 * Dowolna ze zmiennych zwroconych jako obiekt jesli jest null, to znaczy ze w nia tez nie ingerujemy
		 * 
		 * @return {width: X, height: Y}
		 */
		var calculateSubmenuDimensions = function($submenu) {
			// jesli juz raz obliczylismy mu wymiary, to nie robimy tego drugi raz
			if($submenu.data("wsd-dimensions") != undefined) {
				return $submenu.data("wsd-dimensions");
			}
			
			var dimensions = {"width": null, "height": null};
			var displayMode = getLevelStyleType($submenu.data("level"));
			var $parent = $submenu.closest("li"); // (performance: przekazac to w zmiennej)
			
			var allowedWidth = $(window).width();
			
			if(displayMode == "horizontalBar") { 
				var wantedWidth = 0;
				
				// obliczamy szerokość pożądaną przez submenu.
				// na potrzeby $.width() żonglujemy css visibility i display
				$submenu.css("visibility", "hidden").css("display", "block");
				$("> li", $submenu).each(function(i, elem) {
					wantedWidth += $(elem).width();
					
//					console.log($(elem).html()+" width: "+$(elem).width());
					
				});
				
				$submenu.css("display", "none").css("visibility", "visible");
				
				// jesli przekroczylismy dozwolona szerokosc menu - ustawiamy max dozwolona
				/*if(allowedWidth != null && wantedWidth > allowedWidth) {
					//wantedWidth = allowedWidth; // zakomentowane bo sie zle lamie
				}*/
				
				dimensions.width = wantedWidth;
			} else if(displayMode == "box") {
				var wantedWidth = 0;
				var positionCount = 0;
				
				$submenu.css("visibility", "hidden").css("display", "block");
				$("> li:not(.filler)", $submenu).each(function() {
					positionCount++;
					
					if($(this).width() > wantedWidth) {
						wantedWidth = $(this).width();
					}
				});
				
				$submenu.css("display", "none").css("visibility", "visible");
				
				if(allowedWidth != null && wantedWidth > allowedWidth) {
					wantedWidth = allowedWidth;
				}
				var columns = options.levelStyle[$submenu.data("level")].options.columns;
				
				if(positionCount < columns) {
					columns = positionCount;
				}
				
				dimensions.width = wantedWidth * columns;
				
				$submenu.data("wsd-box-columnsCount", columns);
			} else if(displayMode == "verticalBar") {
				var wantedWidth = 0;
				
				// obliczamy szerokość pożądaną przez submenu.
				// na potrzeby $.width() żonglujemy css visibility i display
				$submenu.css("visibility", "hidden").css("display", "block");
				$("> li", $submenu).each(function(i, elem) {
					
					if($(elem).width()> wantedWidth) {
						wantedWidth = $(elem).width() - 15; // wtf?? dlaczego 25??
					}
				});
				$submenu.css("display", "none").css("visibility", "visible");
				
				// jesli przekroczylismy dozwolona szerokosc menu - ustawiamy max dozwolona
				if(allowedWidth != null && wantedWidth > allowedWidth) {
					wantedWidth = allowedWidth;
				}
				dimensions.width = wantedWidth;	
				

				if(wantedWidth > $parent.width()) {
					// vertical nie zmiescil sie pod swoim parentem.

					
					/** rozszerzamy parenta jesli children jest szerszy **
					// jezeli parent jest horizontalem - rozszerzmy ten jeden elmement zeby sie ladnie zmiescilo
					var parentLevel = $parent.data("level");
					var diff = wantedWidth - $parent.width();
					
					if(getLevelStyleType(parentLevel) == "horizontalBar" && $parent.hasClass("wsd-last")) {
						var $parentContainer = $parent.closest("ul");
						var parentContainerDimensions = $parentContainer.data("wsd-dimensions");
						
						parentContainerDimensions.width += diff;
						
						$parentContainer.data("wsd-dimensions", parentContainerDimensions).css("width", parentContainerDimensions.width+"px");
						$parent.css("width", wantedWidth+"px");
						
					}
				*/
				}
			}
			
			$submenu.data("wsd-dimensions", dimensions);
			return dimensions;
		}
		
		/**
		 * Otwiera wskazane submenu
		 */
		var openSubmenu = function(e) {
			var $triggerElement = $(this);
			var $submenuContainer = $("> ul:nth(0)", $triggerElement);
			var level = $triggerElement.data("level");
			var displayMode = getLevelStyleType(1+level);
			
			// dodajemy css markup dla tego submenu
			// robimy to tylko raz, on demand
			if(!$submenuContainer.hasClass("wsd-level"+(1+level))) {
				$submenuContainer.addClass("wsd-level"+(1+level)).data("level", (1+level));
			}
			
			$menu.trigger("submenu.showPrepare", $submenuContainer);
			
			if(displayMode == "box") {
				if($submenuContainer.data("wsd-markupApplied") != true) {
					$submenuContainer.append('<li class="filler">&nbsp;</li>');
				}
			}

			// obliczamy wymiary submenu
			var subDimensions = calculateSubmenuDimensions($submenuContainer);
			
			$submenuContainer.css("width", subDimensions.width+"px");
			if(subDimensions.height != null) {
				$submenuContainer.css("height", subDimensions.height+"px");
			}
			
			// dodajemy niezbedny css markup dla tego submenu
			addSubmenuCssMarkup($submenuContainer);

			// obliczamy pozycje dla submenu
			var subPos = calculateSubmenuPosition($triggerElement, $submenuContainer);
			$submenuContainer.css("top", subPos.y).css("left", subPos.x);

			$menu.trigger("submenu.preShow", $submenuContainer);
			
			// faktycznie pokazujemy submenu
			$triggerElement.addClass("wsd-active");
			$submenuContainer.addClass("wsd-visible").show();
			$menu.trigger("submenu.postShow", $submenuContainer);

			$triggerElement.bind(options.closeEvent, closeSubmenu);
			$("> li.expandable", $submenuContainer).bind(options.openEvent, openSubmenu).data("level", 1+$triggerElement.data("level"));
			$submenuContainer.data("wsd-markupApplied", true);
		};
		
		var closeSubmenu = function(e) {
			var $triggerElement = $(this);
			
			$menuContainer = $("> ul:nth(0)", $triggerElement);

			$menu.trigger("submenu.preHide", $menuContainer);
			$menuContainer.hide().removeClass("wsd-visible");
			$triggerElement.removeClass("wsd-active");
			
			$("> li", $triggerElement).unbind(options.openEvent, openSubmenu);
		};
		
		return this.each(function() {
			$menu = $(this);
			addCssMarkup();
			
			$("li", $menu).each(function(i, elem) {
				var $li = $(elem);
				
				// podpinamy cala nasza logike tylko, jesli dany element ma jakiekolwiek submenu
				if($li.children("ul").length > 0) {
					$li.addClass("expandable");
				}
			});
			
			$("> li.expandable", $menu).bind(options.openEvent, openSubmenu).data("level", 1);
			
		});
	};
})(jQuery);
