(function($){
  $.fn.extend({
    dropDownMenu: function(opts) {
      var defaults = {
        maxItemsPerColumn: 8,
        menuItemSelector: 'li',
        menuContainerSelector: '.menuContainer',
        menuSelector: '.menu',
        menuOpenStateSelector: '.navSprite',
        openStateClass: 'hoverState',
        horizOffset: 0,
        vertOffset: 0
      };
        
      var options = $.extend(defaults, opts);
      var std_line_height = false;
      var std_column_width = false;
      
      return this.each(function() {
        var close_menu = false;
        var o = options;
        var menu_items = $(o.menuItemSelector, this);
        
        if (std_column_width === false) {
          std_column_width = $(o.menuItemSelector + ':first', this).width();
        }
       
        menu_items.hover(function() { // over
          close_menu = false;
          $(o.menuOpenStateSelector, this).addClass(o.openStateClass);
          var left = $(this).position().left + o.horizOffset;
          var top = $(this).position().top + $(this).height() + o.vertOffset;
          var margin = parseInt($(this).css('margin-left'), 10) + parseInt($(this).css('margin-right'), 10);
          
          var menu = $(o.menuContainerSelector, this);
          
          menu.css({
            'left':left,
            'top':top,
            'width':std_column_width
          })
          .addClass('open')
          .show(0, function() {
            if (std_line_height === false) {
              var baseline = $(o.menuSelector + ' ul li a:first', this);
              var current = baseline.html();
              baseline.html('A');
              std_line_height = baseline.height();
              baseline.html(current);
            }
            
            var items = $(o.menuSelector + ' li', this);
            var new_layout = '<div class="menuColumn"><ul>';
            var item_cnt = 0;
            var col_cnt = 1;
            
            for (var i = 0; i < items.length; i++) {
              var classes = $(items[i]).attr('class');
              
              if (classes.length > 0) { classes = ' class="' + classes + '"'; }
              
              new_layout += '<li' + classes + '>' + $(items[i]).html() + '</li>';
              item_cnt++;
              if (item_cnt >= o.maxItemsPerColumn) {
                new_layout += '</ul></div>';
                if (i < items.length - 1) {
                  new_layout += '<div class="menuColumn"><ul>';
                  col_cnt++;
                }
                item_cnt = 0;
              }
            }
            
            new_layout += '</div>';
            
            var tm = $(o.menuSelector, menu);
            
            var new_width = (col_cnt * std_column_width) + ((col_cnt - 1) * margin);
            
            tm.html(new_layout).width(new_width);
            
            
            var overflowed = false;
            
            var new_menu_width = std_column_width;
            var new_col_width = std_column_width;
            
            $(this).find('.menuColumn li a').each(function() {
              new_menu_width = std_column_width;
              new_col_width = std_column_width;
              
              if ($(this).height() > std_line_height || $(this).width() > std_column_width) {
                if (col_cnt == 1) {
                  new_menu_width = (std_column_width * 2) + margin;
                  new_col_width = (std_column_width * 2) + margin;
                } else {
                  new_menu_width = (std_column_width * 3) + (margin * 2);
                  new_col_width = (std_column_width * 1.5) + margin;
                }
                $('li', menu).width(new_col_width);
                menu.width(new_menu_width);
                menu.find(o.menuSelector).width(new_menu_width);
                
                overflowed = true;
                return false;
              } else { return true; }
            });
            
            $('.menuColumn', this).width(new_col_width);
            
            if (!overflowed) {
              menu.width(std_column_width);
              $('li', menu).width(std_column_width);
            }
          }); // show() callback
        }, function() { // out
          $(o.menuContainerSelector, this).removeClass('open').hide();
          $(o.menuOpenStateSelector, this).removeClass(o.openStateClass);
        }); // hover()
      }); // each()  
    } // dropDownMenu()
  }); // $.extend()  
})(jQuery); // anon()
