jQuery.fn.accmenu = function () {
  return this.each(function () {

    var m = $.fn.accmenu;
    var lib = hsp;
    var ios = lib.ios;
    var mobile = ios;
    var opts = m.defaults;
    var root = $(this);
    m.mode = opts.mode; // can be 'small' or 'big', depending on window width
    m.root = root;
    m.wrapper = root.parents('#nav-wrapper');
    if (ios) {
      m.wrapper.wrap('<div id="hiding-wrapper"></div>')
      m.hidingWrapper = root.parents('#hiding-wrapper');
    }
    m.hidden = root.parents('#nav-hidden');
    m.toggleElem = opts.toggle;
    m.toggleOben = opts.toggleOben;
    m.vonoben = opts.vonoben;
    m.open = false;

    if (opts.toggleHeight == undefined) {
      m.toggleHeight = opts.toggle.outerHeight(true);
    } else {
      m.toggleHeight = opts.toggleHeight;
    }
    
    opts.toggle.addClass('closed');
    // now hide the sub ul's
    root.find('ul').css({
      display : 'none'
    });
    
    // mark the second and third levels with css classes for easy styling
    root.children().children('ul').each(function () {
      var second = $(this);
      second.addClass('second-level');
      second.children().children('ul').each(function () {
        var third = $(this);
        third.addClass('third-level');
      });
    });


    // add the click handler to the links
    var sel = '.'+opts.sel;
    m.clickhandler =function () {
      var li = $(this).parent();
      var selected = li.hasClass(opts.sel);

      if (selected) {
        // the item is selected, so we remove the selection
        li.removeClass(opts.sel);
        // and hide the sublist
        var sub = li.children('ul');
        m.hideElem(sub);
      } else {
        // the li is not yet selected, but shall be selected
        // find selected siblings and hide their child lists
        li.siblings(sel).find("ul").each(
          function () {
            m.hideElem($(this));
          });
        // and remove their selections
        li.siblings(sel).find("ul li"+sel).removeClass(opts.sel);
        li.siblings(sel).removeClass(opts.sel);
        // set selection
        li.addClass(opts.sel);
        // show sublist
        var sublist = li.children('ul');
        // TODO is the next line correct?
        if (sublist.length) {
          if (sublist.hasClass('third-level')){
            var remainingheight = m.remainingHeight();
            lib.info('remaining Height:'+remainingheight);
            sublist.css({
              height:'auto'
            });
            var fullheight = sublist.outerHeight(true);
            sublist.css({
              height : 0,
              display : 'block',
              overflow : 'hidden'
            });
            if (mobile) {
              // on mobile, we always show the complete menu, as it would otherwise not be reachable
              // for the user
              remainingheight = fullheight;
            }
            var resultheight = Math.min(fullheight,remainingheight);
            var cb = function () {
              // if we can show the fullheight, we set the height to auto, to disable scrollbars
              if (resultheight === fullheight) {
                sublist.height('auto');
              }
              sublist.css('overflow','auto');
            }
            sublist.animate({
              height:resultheight
            },400,cb);
          } else {
            // not third-level
            m.showElem(sublist);
          }
        }
        opts.onselection();
      }
    }
    root.find('a').click(m.clickhandler);
  // attach click handler to toggle elem now done in custom.js.
  });

    
}; // end of accmenu()

// now add some functions to the plugin
(function(){

  var $ = jQuery;
  var m = $.fn.accmenu;
  var lib = hsp;
  var ios = lib.ios;

  m.mode = 'big';
  m.wrapperAnimated = false;

  m.setMode = function (mode) {
    m.mode = (mode == 'small')?'small':'big';
    lib.info('menu mode set: '+m.mode);
  }

  m.showElem = function showElem(e) {
    e.css({
      height: 'auto',
      display: 'block'
    });
    var h = e.outerHeight(true);
    //    console.log('h: '+h);
    e.height(0);
    e.animate({
      height:h
    },200,'swing',function () {
      e.height('auto')
    });

  }
  m.hideElem = function hideElem(e) {
    e.animate({
      height:0
    },200,'swing',function () {
      e.css('display','none')
    });
  }
  m.maxHeight = function () {
    var h = $(window).height();
    if (m.mode == 'small') {
      return h;
    } else {
      return h - m.defaults.marginTop;
    }
  }

  m.remainingHeight = function () {
    var h =  m.maxHeight()- m.wrapper.outerHeight(true);
    if (h < m.defaults.minHeight) {
      h = m.defaults.minHeight
    }
    return h;
  }
  
  m.toggle = function () {
    lib.info('menu.toggle()');
    if (m.wrapperAnimated) {
      lib.info('menu click discarded, because in animation');
      return;
    }
    if (m.visible()) {
      m.hide();
    } else {
      m.show();
    }
  }

  m.visible = function () {
    return m.toggleElem.hasClass('open');
  }

  m.hiddenHeight = function () {
    var h = m.hidden.outerHeight(true);
    return h;
  }
  m.totalHeight = function () {
    var h =  m.toggleHeight + m.hiddenHeight();
    return h;
  }

  if (ios) {
    // using webkit animation
    m.wrapperto = function wrapperto(h,cb) {
      lib.info('webkit wrapperto called, h:'+h);
      m.wrapperAnimated = true;
      var hh = Math.max(h,m.hidingWrapper.height());
      m.hidingWrapper.css({
        overflow: 'hidden',
        height: hh
      });

      var listener = function () {
        m.hidingWrapper.css({
          overflow: 'visible'
        });
        m.wrapper.css({
          '-webkit-transition-duration' : '0s'
        });
        cb();
        // set hidingWrapper to target height, so that it does not overlay content
        m.hidingWrapper.css({
          height: h
        });
        // the listener removes himself
        m.wrapperAnimated = false;
        m.wrapper[0].removeEventListener('webkitTransitionEnd', listener, false);
      }
      m.wrapper.css({
        '-webkit-transition-property' : 'height',
        '-webkit-transition-duration' : '400ms'
      });
      m.wrapper[0].addEventListener('webkitTransitionEnd',listener ,false)
      // trigger transition
      m.wrapper.css('height',h);
    }
  } else {
    // using jquery animation
    m.wrapperto = function (h,cb) {
      m.wrapperAnimated = true;
      var callback = function () {
        m.wrapperAnimated = false;
        cb();
      }
      m.wrapper.animate({
        height : h
      },m.defaults.duration,m.defaults.easing,callback);
    }
  }

  if (ios) {
    m.adjust = function (cb) {
      var h = m.totalHeight();
      m.wrapperto(h, cb);
    }

  } else {
    m.adjust = function (cb) {
      var h = m.totalHeight();
      m.wrapperto(h, cb);
    }

  }

  m.show = function () {
    if (m.open) {
      return;
    }
    m.open = true;
    // shows the whole navi
    if (m.vonoben)
    {
      m.hidden.css({
        position: 'absolute',
        bottom: 0
      });
    } else {
      
    }
    
    m.adjust(function () {
      if (m.vonoben) {
        m.hidden.css({
          position : 'static'
        });
      }
      m.wrapper.css({
        height : 'auto'
      })
      m.toggleElem.removeClass('closed');
      m.toggleElem.addClass('open');
      m.toggleOben.removeClass('closed');
      m.toggleOben.addClass('open');
    });
  }

  m.hideIfSmall = function hideIfSmall() {
    if (ios || (m.mode == 'small')) {
      m.hide();
    }
  }

  m.hide= function hide() {
    if (!m.open) {
      return;
    }
    m.open = false;
    var cb = function () {
      m.hidden.css({
        position: 'static'
      });
      m.toggleElem.removeClass('open');
      m.toggleElem.addClass('closed');
      m.toggleOben.removeClass('open');
      m.toggleOben.addClass('closed');
    }
    if (m.vonoben) {
      // when animating from above we want the nav content to stick to the bottom of the animated
      // wrapper
      var h = m.wrapper.height();
      m.wrapper.height(h);
      m.hidden.css({
        position: 'absolute',
        bottom: 0
      });
    } else {
      m.hidden.css({
        position: 'static',
        bottom: 'auto'
      })
    }

    m.wrapperto(m.toggleHeight, cb);
    
  }

  m.height= function () {
    var h = $.fn.accmenu.root.outerHeight(true);
    return h;
  }

  m.set= function set(link,clear) {
    var opts = m.defaults;
    // looks for a link whith the given href and selects it
    // may be called after page load or after a content load by a link not in the nav menu

    // if clear is set, all selection shall be cleared
    if (clear) {
      // remove selections
      m.root.find('li').removeClass(opts.sel);
      // make the child ul's invisible
      m.root.find('ul').css('display','none');
    }
    if (!link) {
      return;
    }
    var match=$('a[href*='+link+']',m.root).eq(0);

    if (!match) {
      lib.info('menu.set did not find link');
      return;
    }
    // we found a link with this popup
    match.parents("li",m.root).addClass(opts.sel);
    // make the ul's visible
    match.parents("ul",m.root).show().height('auto');
  }
})(); // immediately call the function

$.fn.accmenu.setdefault = function (options) {
  var opts = jQuery.extend({}, $.fn.accmenu.defaults, options);
  $.fn.accmenu.defaults = opts;
}

/*
 * duration : duration of the animation
 * easing :
 * marginTop : the space left by the navigation on top of screen
 * minHeight : the minimum height for the third level to have if there is no remaining space
 * toggle : the elem which shall toggle the navi
 * toggleHeight : the height of the toggle elem if it is inside the wrapper
 *   (if undefined it is taken from toggle elem)
 */
$.fn.accmenu.defaults = {
  mode : 'small',
  vonoben : false,
  duration : 400,
  easing : 'swing',
  marginTop : 50,
  minHeight : 50,
  toggle : undefined,
  toggleOben : undefined,
  toggleHeight : undefined,
  sel : 'accmenu-selected',
  onselection : function () {}
};







