/*
expects html in the following form:
<optional nav/div>
   <ul>
      <li>
         <a href="#"><div>1st level</div></a>
         <ul>
            <li>
               <a href="#"><div>2nd level</div></a>
               <ul>
                  <li>
                     <a href="#"><div>3rd level</div></a>
                  </li>
               </ul>
            </li>
         </ul>
      </li>
   </ul>
</optional nav/div>
*/

(function($){
   $.fn.menuify = function (options) {
      var settings = {};
      settings.stop_after = 'custom';
      jQuery.extend(settings, options || {});
      
      var linked = $(this).menuify_gettargets();
      var _this = this;
      $(linked).each(function(i, e){
         // binding hover to 'li > a' instead of 'li' otherwise the mouseover will not fire when moving back from 'li > ul'
         e.el.find('> a').hover(function(){
            _this.menuify_clearFade(e.menu, e.id);
            e.menu.stop(true, true);
            e.el.find('> a').addClass('menu-open');
            e.menu.slideDown(200);
         }, function(){
            _this.menuify_queueFade(e.menu, e.id);
            e.el.find('> a').removeClass('menu-open');
         });
         
         // bind a similar hover to 'li > ul' to clear and recreate the fadeout timer
         e.menu.hover(function(){
            _this.menuify_clearFade(e.menu, e.id);
            e.menu.stop(true, true);
            e.el.find('> a').addClass('menu-open');
            e.menu.fadeIn(150);
         }, function(){
            _this.menuify_queueFade(e.menu, e.id);
            e.el.find('> a').removeClass('menu-open');
         });
      });
      jQuery.data($(this)[0], 'menuify_config',{
         timeouts: {}
      });
      
      // we have to go deeper >.>
      $(linked).each(function(i, e){
         if(e.menu && e.menu.length > 0 && !e.el.hasClass(settings.stop_after))
            e.menu.menuify(settings);
      });
   }
   $.fn.menuify_queueFade = function(target, id){
      var config = jQuery.data(this[0], 'menuify_config');
      var timeouts = config.timeouts;
      $(target).css('zIndex', 100);
      
      if(config.timeouts[id])
         clearTimeout(config.timeouts[id]);
      
      config.timeouts[id] = setTimeout(function(){
         $(target).slideUp(200);
      }, 50);
      jQuery.data(this[0], 'menuify_config', config);
   }
   $.fn.menuify_clearFade = function(target, id){
      var config = jQuery.data(this[0], 'menuify_config');
      var timeouts = config.timeouts;
      $(target).css('zIndex', 200);
      if(config.timeouts[id])
         clearTimeout(config.timeouts[id]);
   }
   
   // The <li>s we're after are direct children of $(this) or $(this).find('> ul')
   $.fn.menuify_gettargets = function() {
      var linked = [];
      var children = $(this).find('> li');
      if(children.length == 0)
         children = $(this).find('> ul > li');
      
      $(children).each(function(i, e){
         linked.push({
            el: $(e),
            menu: $(e).find('> ul'),
            // id is used to track the fade timeout associated with the menu
            id: i
         });
      });
      return linked;
   }
})(jQuery);

