jQuery(function($) {
  
  if ( $('#colcontent.wide').length ) specialWide();
  if ( $('#carousel').length ) carousel();
  if ( $('#serviceMenu').length ) serviceMenu();
  if ( $('#mainNav').length ) mainNav();
  if ( $('#slideShow').length ) slideShow();
  
  // ************************************* //
  // Special Wide Template with hidden Nav //
  // ************************************* //
  
  function specialWide () {
    $('#colcontent').removeClass().addClass('specialWide');
    var subNav = $('#subNav');
    
    $('#content').prepend('<a id="showNav" href="#">Navigation anzeigen &raquo;</a>');
    subNav.prepend('<a id="hideNav" href="#"><span class="hidden">Navigation schließen</span></a>');
    
    $('#showNav').click(function() {
      subNav
        .fadeIn({duration: 500, easing:'cubicEaseInOut' })
        .find('a').eq(0).focus();
      return false;
    });
    $('#hideNav').click(function() {
      subNav.fadeOut({duration: 500, easing:'cubicEaseInOut' });
      $('#showNav').focus();
      
      return false;
    });
  }  
  
  // ******** //
  // Carousel //
  // ******** //
  
  function carousel () {
  // Elements
    var carouselList = $('#carousel ul');
    
    // insert prev / next Buttons
    carouselList
      .before('<a id="carouselPrevButton" href="#" tabindex="-1"><span class="hidden">Zurück</span></a>')
      .after('<a id="carouselNextButton" href="#" tabindex="-1"><span class="hidden">Weiter</span></a>');
    var prevLink = $('#carouselPrevButton');
    var nextLink = $('#carouselNextButton');
    var listItems = carouselList.find('li');
    var titleLinks = listItems.find('a');
    
    // Common Vars  
    var inCarousel = false;
    var teaserIndex = 1;
    var teaserCount = listItems.length;
    var pageIndex = 1;
    var pageCount = Math.ceil(listItems.length / 3);
    
    // "Constants"
    var ANIM_LENGTH = 63.5;
    var ANIM_DURATION = 900;
    var ANIM_EASING = 'expoEaseInOut';
    
    // click previous Link
    prevLink.click(function() {
      changePage(-1);
      return false;
    });
    
    // click next Link
    nextLink.click(function() {
      changePage(+1);
      return false;
    });
    
    // change to next (dir=1) or previous (dir=-1) page
    // if on first or last page, reacts accordingly
    function changePage (dir, callback) {
      var animLength = '-=' + ANIM_LENGTH * dir + 'em';
      // this is just for a IE 7 Bug
      if ( dir > 0 ) animLength = '-' + ANIM_LENGTH * pageIndex + 'em';
      
      if ( dir < 0 && pageIndex == 1 ) {
        animLength = '-' + ANIM_LENGTH * (pageCount - 1) + 'em';
        pageIndex = pageCount+1; // +1 because it gets decreased later
      } else if ( dir > 0 && pageIndex == pageCount ) {
        animLength = '-=' + carouselList.css('left'); // we don't just set it to "0" because of, guess what, IE yes
        pageIndex = 0; // 0 because it gets increased later
      }
      
      carouselList.animate(
        {left: animLength},
        ANIM_DURATION,
        ANIM_EASING,
        callback
      );
      
      pageIndex += dir;
    }
    
    titleLinks
    .focus(function(e) {
      // focus the first element when the last one is focused from outside
      if ( !$(this).closest('li').next().length && !inCarousel ) {
        e.preventDefault();
        titleLinks.eq(0).focus();
      }
      
      inCarousel = true;
    })
    .keydown(function(e) {
      // tabbing through the carousel
      teaserIndex = $(this).closest('li').prevAll().length + 1;
      
      if ( e.keyCode == 9 && e.shiftKey ) { // we should go back
        if ( teaserIndex == 1 ) { // leave if we are at the begining
          inCarousel = false;
          return;
        } 
        if ( teaserIndex%3 == 1 ) { // go to previous page
          e.preventDefault();
          changePage(-1, function() {
            titleLinks.eq(teaserIndex-2).focus();
          });
        }
      } else if ( e.keyCode == 9 && !e.shiftKey ) { // we should go forward
        if ( teaserIndex == teaserCount ) { // reset and leave if we are at the end
          inCarousel = false;
          teaserIndex = 1;
          changePage(+1);
          return; 
        }
        if ( teaserIndex%3 == 0 ) { // go to next page
          e.preventDefault();
          changePage(+1, function() {
            titleLinks.eq(teaserIndex).focus();
          });
        }
      }
    });
  }
  
  // ************ //
  // Service Menu //
  // ************ //
  
  function serviceMenu () {
    var serviceMenu = $('#serviceMenu');
    
    serviceMenu.prepend('<div class="spacer"></div>').children('.spacer').width(serviceMenu.width());
    
    serviceMenu
    .hover(
      function() {
        $(this).addClass('open');
      },
      
      function() {
        $(this).removeClass('open');
      }
    )
    .click(function() {
      window.location.href = $(this).find('a').attr('href');
    })
    .children('a')
    .focus(function() {
      $(this).parent().addClass('open');
    })
    .blur(function() {
      $(this).parent().removeClass('open');
    });
  }
  
  // *************** //
  // Main Navigation //
  // *************** //
  
  function mainNav () {
    // Elements
    var mainNav = $('#mainNav');
    var firstLevelLi = mainNav.children('ul').children('li');
    
    // "Constants"
    var TWO_COL_LIMIT = 4;
    var THREE_COL_LIMIT = 9;
    
    // For each First Level Element
    firstLevelLi.each(function() {
      var element = $(this);
      var link = element.children('a');
      var list = element.children('ul.secondLevel');
      var innerLi = list.children('li:not(.first)');
      var innerLiCount = innerLi.length;
      
      // Add a Spacer Div to make the gap
      link.after('<div class="spacer">&nbsp;</div>').next('.spacer').width(element.width());
      
      // Open & Close Flyout on click
      link.click(function() {
        var isOpen = element.hasClass('open');
        firstLevelLi.removeClass('open').children('ul.secondLevel').hide();
        
        if (! isOpen ) {
          element.addClass('open');
          list.show();
        }
        
        // Close Flyout on click anywhere
        $('body').one('click', function(e) {
          firstLevelLi.removeClass('open').children('ul.secondLevel').hide();
        });
        
        element.keydown(function(e) {
          if ( e.keyCode == 27 ) {
            firstLevelLi.removeClass('open').children('ul.secondLevel').hide();
            link.focus();
            element.unbind('keydown');
          }
        });
   
        return false;
      });
      
      // Close all Flyouts when firstLevelLi is focused
      /* link.focus(function() {
        firstLevelLi.removeClass('open').children('ul.secondLevel').hide();
      }); */
      
      // If there are more than TWO_COL_LIMIT elements we need columns
      if ( innerLiCount >= TWO_COL_LIMIT ) {
        var ulClass = innerLiCount >= THREE_COL_LIMIT ? 'threeCols' : 'twoCols';
        var colCount = ulClass == 'twoCols' ? 2 : 3;
        var elementsPerCol = Math.ceil(innerLiCount / colCount);
        
        // add Column class and wrap into columns
        list.addClass(ulClass);
        for (var i=1; i<=colCount; i++) {
          list.children('li:not(.first, .fakeCol):lt('+elementsPerCol+')')
            .wrapAll('<li class="fakeCol row'+i+'"><ul></ul></li>')
            .eq(0).closest('li.fakeCol').prepend('<span class="hidden">Submenü Spalte '+i+'</span>');
        }
      }
      
      // positioning when we are too far right
      var rightOffset = $('#pagecenter').width() - (list.outerWidth() + element.position().left);
      
      if ( rightOffset < 0 ) { // we are to far right
        list.css({ left: rightOffset-1});
      }
    });
  }
  
  // ********* //
  // Slideshow //
  // ********* //
  
  function slideShow () {    
    var slideShow = $('#slideShow');
    var slides = slideShow.children('img');
    
    // if there is only one image we don't want a slideshow
    if ( slides.length <= 1 ) return;
    
    slides.hide();
    var current = slides.eq(0).show();
    
    // Constants
    var FADE_TIME = 1800;
    var SHOW_TIME = 6000;
    var EASING = 'cubicEaseInOut';
    
    // Add Play / Pause Buttons and hide the play button
    slideShow.prepend('<a id="slideShowPlay" href="#"><span class="hidden">Play</span></a> <a id="slideShowPause" href="#"><span class="hidden">Pause</span></a>');
    var slidePause = $('#slideShowPause').click(pause);
    var slidePlay = $('#slideShowPlay').hide().click(play);
    
    // Start the slideshow in an interval
    var interval = setInterval(changeSlide, SHOW_TIME);
    
    // Find out the next slide, animate the change
    // and then make the next slide the current one
    function changeSlide () {
      var next = current.next();
      
      if (! next.length ) {
        next = slideShow.children('img:first');
      }
      
      animateChange(current, next);
      current = next;
    }
    
    // Change from to currentSlide to nextSlide
    function animateChange (currentSlide, nextSlide) {
      currentSlide.fadeOut({duration: FADE_TIME, easing: EASING});
      nextSlide.fadeIn({duration: FADE_TIME, easing: EASING})
    }
    
    // Stop Playing and change the buttons
    function pause () {
      clearInterval(interval);
      
      slidePause.fadeOut({duration: 300, easing: EASING});
      slidePlay.fadeIn({duration: 300, easing: EASING});
      
      return false;
    }
    
    // Start Playing immediately and in interval and change the buttons
    function play () {
      changeSlide();
      interval = setInterval(changeSlide, SHOW_TIME);
      
      slidePlay.fadeOut({duration: 300, easing: EASING});
      slidePause.fadeIn({duration: 300, easing: EASING});
      
      return false;
    }
  }
});
