(function($) {

  /* -- Tabs functionality (multiple triggers switching between multiple targets) -- */

  $.fn.tabPanels = function() {
    return $(this).map( function(i, v) {
      
      var p = $($(this).attr("href")); 
      
      if (p.length > 0) {
        return p[0];
      }
    });
  };
  
  $.fn.tabs = function(selector, noSelect){
    this.each(function(){
       
       var p = $(this);
       var tabs = $(selector || 'a', p);
       
       var panels = tabs.tabPanels(); 
       
       tabs.click(function(event){
         panels.hide();
         $('.current', p).removeClass('current');
          
         var panel = $(this).tabPanels();
         
         if (panel)
            panel.show();
          
         $(this).addClass('current');
         event.preventDefault();
       });
       
       
       if (!noSelect) {
         tabs.filter(":first").click();
       }
    });
    
    return this;      
  };
  
  /* -- Tooltip creation and behaviour -- */
  $.tooltipCreate = function(data) {
    $($.tmpl( $.SITE_TEMPLATES.TOOLTIP, $.extend({className: ""}, data))).appendTo("body");
  };
  
  $.fn.tooltip = function() {  
    
    var tooltips = $(this);
    
    $(this).each( function() {

      $(this)
        .reveal( function(trigger) { if ($(trigger).metadata().tooltipId) { return $('#' + $(trigger).metadata().tooltipId); } }, {
          event: $(this).metadata().event || "mouseenter", 
          hideOnTargetMouseLeave: $(this).metadata().hideOnTargetMouseLeave != undefined ? $(this).metadata().hideOnTargetMouseLeave : true, 
          affixOptions: $(this).metadata().affixOptions || {from: "sw", to: "c", offsets: [-50, -8]},
          hideTimeout: 200,
          classShown: "tooltip_shown",
          fShow: function(el) { el.fadeIn($.fadeDuration("fast")); },
          fHide: function(el) { el.fadeOut($.fadeDuration("fast")); }
        })
        .bind("reveal.beforeshow", function( event ) { tooltips.not($(event.target)).revealHide(); } );
      
    });
    
    return this;
  };

  /* ---- Global Fade Duration ---- */
  
  $.fadeDuration = function(duration) {
    return $.browser.msie ? 0 : duration || "normal";
  };
  
  /* ---- Anchor Utility (convenience wrapper for the very bizarre URL plug-in syntax) ---- */
  
  $.fn.anchor = function() {
    return $.url.setUrl($(this).attr("href")).attr("anchor") || "";
  };

  $.fn.file = function() {
    return $.url.setUrl($(this).attr("href")).attr("file") || "";
  };

  function basename(path, suffix) {
      // http://kevin.vanzonneveld.net

      var b = path.replace(/^.*[\/\\]/g, '');

      if (typeof(suffix) == 'string' && b.substr(b.length-suffix.length) == suffix) {
          b = b.substr(0, b.length-suffix.length);
      }

      return b;
  }
  
  $.fn.basename = function(suffix) {
    return basename($(this).file(), suffix);
  };
  
  // make a utility on the jQuery object, to get the anchor for the current URL 
  $.anchor = function() {
    return $.url.attr("anchor");
  };

  /* ---- Panel Scroller ---- */
  
  $.fn.scroller = function(options) {
  
    $(this).each( function() {
    
      $(this).css("overflow", "hidden");
      $(".panel_content,.panel_title", this).css("overflow", "hidden");
      
      var scroller = $(this);
    
      var s = $.extend( {
        viewWidth: 865,
        trainSelector: ".scroller_train",
        itemSelector: "li.panel",
        clickSelector: "li.panel .panel_title",
        arrowKeyEvents: true,
        mousewheelEvents: true,
        mouseWheelIgnoreSelector: '.panel_reveal_content',
        arrowKeyIgnoreSelector: 'input,textarea'
      }, options || {});

      $(this).data("scroller-train", $(s.trainSelector, this));
      $(this).data("scroller-origin", $(this).outerWidth());
      $(this).data("scroller-settings", s);
      $(this).data("scroller-index", 0);
      $(this).data("scroller-position", 0);
              
      var train = $(this).data("scroller-train");
      var scroller = $(this);
    
      $(this).data("scroller-click", function(event) {
        var el = $(event.target).closest(s.itemSelector).eq(0);
        
        if (el.length > 0)
          $(scroller).scrollerTo(el[0]);
      });
      
      
      
      // setup the initial state
      $(s.clickSelector, scroller).click($(this).data("scroller-click"));
      
      $(s.itemSelector, scroller)
        .find(".panel_title").show()
        .end()
        .eq(0)
        .find(".panel_title").hide();
    
      // setup arrow key events 
    
      if (s.arrowKeyEvents) {
        
        $(this).data("scroller-keydown", function(event) {

          var scroll = true;

          if (s.arrowKeyIgnoreSelector) {
            scroll =  ( $(event.target).closest(s.arrowKeyIgnoreSelector).length == 0 );
          }

          if (scroll) {
            var key = event.charCode || event.keyCode || 0;

            if (key == 39) {
             $(scroller).scrollerNext();
            } else if (key == 37) {
              $(scroller).scrollerPrevious();
            }
          }

        });
        
        $(document).keydown( $(this).data("scroller-keydown") );
      }
    
      if (s.mousewheelEvents) {
        
        $(this).data("scroller-mousewheel", function(event, delta) {
        
          var scroll = true;
        
          if (s.mouseWheelIgnoreSelector) {
            scroll =  ( $(event.target).closest(s.mouseWheelIgnoreSelector).length == 0 );
          }
        
          if (scroll) {
            if (delta > 0) {
              $(scroller).scrollerPrevious();
            } else {
              $(scroller).scrollerNext();
            }          
          }
        });
        
        scroller.bind('mousewheel', $(this).data("scroller-mousewheel"));
      }
    
      $(scroller).scrollerUpdateOrigin();
    });
  
  };

  $.fn.scrollerDestroy = function() {
    $(this).each( function() {
      
      if ($(this).data("scroller-click"))
        $(this).unbind("click", $(this).data("scroller-click"));

      if ($(this).data("scroller-keydown"))
        $(document).unbind("keydown", $(this).data("scroller-keydown"));

      if ($(this).data("scroller-mousewheel"))
        $(document).unbind("mousewheel", $(this).data("scroller-mousewheel"));

    });
  };

  
  $.fn.scrollerDisable = function() {
    $(this).each( function() {
      $(this).data("scroller-disabled", true);
    });
  };

  $.fn.scrollerEnable = function() {
    $(this).each( function() {
      $(this).data("scroller-disabled", null);
    });
  };


  $.fn.scrollerUpdateOrigin = function(bypassEvents) {
    $(this).each( function() {
      var s = $(this).data("scroller-settings");
      
      $(this).data("scroller-origin", Math.max(0, Math.round( ( $(this).outerWidth() - s.viewWidth ) / 2 )));
      $(this).scrollerUpdate(true, bypassEvents);
    });
  };
  
  $.fn.scrollerUpdate = function(instant, bypassEvents) {
   $(this).each( function() {
   
     if (!$(this).data("scroller-animating")) {
   
       var scroller = $(this);
     
       var train = $(scroller).data("scroller-train");
       var s = $(scroller).data("scroller-settings");
       var o = $(scroller).data("scroller-origin");

       var item = $(s.itemSelector + ':eq(' + $(this).data("scroller-index") + ')', $(this));
       var itemCount = $(s.itemSelector).length;
   
       var afterComplete = function() {
           
         if (!bypassEvents) {
              $(scroller).trigger("scroller.afterscroll", [item, instant]);
            
         if ($(scroller).data("scroller-index") == 0) {
            $(scroller).trigger("scroller.afterscrolllowerlimit", [item, instant]);
          } else if ($(scroller).data("scroller-index") == itemCount - 1) {
            $(scroller).trigger("scroller.afterscrollupperlimit", [item, instant]);
          }
        
         }
         
         $(scroller).data("scroller-animating", false);
       };
   
      // trigger limit events

      if (!bypassEvents) {
      
       if ($(scroller).data("scroller-index") == 0) {
         $(scroller).trigger("scroller.beforescrolllowerlimit", [item, instant]);
       } else if ($(this).data("scroller-index") == itemCount - 1) {
         $(scroller).trigger("scroller.beforescrollupperlimit", [item, instant]);
       }
     }
     
       if (instant) {
         $(train).css({"left": o  - $(item).position().left } );
         afterComplete();
       }
       else {
         $(scroller).data("scroller-animating", true);
         $(train).animate({"left": o  - $(item).position().left }, { easing: "easeOutQuart", complete: afterComplete } );
       }
     }
   });
 
   return $(this);
  };

  $.fn.scrollerNext = function(instant) {
   $(this).each( function() {


     if (!$(this).data("scroller-animating") && !$(this).data("scroller-disabled")) {

       var s = $(this).data("scroller-settings");
       var itemCount = $(s.itemSelector).length;
       var item = $(s.itemSelector + ':eq(' + $(this).data("scroller-index") + ')', $(this));
      
       if ($(this).data("scroller-index") < itemCount - 1) { 

         $(this).trigger("scroller.beforescrollnext", [item, instant]);
         $(this).trigger("scroller.beforescroll", [item, instant]);

         $(this).data("scroller-index", $(this).data("scroller-index") + 1);


         $(this).scrollerUpdate(instant);
       }
     }

   });
 
   return $(this);       
  };

  $.fn.scrollerTo = function(el, instant) {
  
    $(this).each( function() {
  
      if (!$(this).data("scroller-animating") && !$(this).data("scroller-disabled")) {
  
        var s = $(this).data("scroller-settings");
        var items = $(s.itemSelector);
        var i = 0;
    
        var item = $(s.itemSelector + ':eq(' + $(this).data("scroller-index") + ')', $(this));

        items.each( function(index, item) {
          if (item == el) {
            i = index;
          }
        });
        
        if ($(this).data("scroller-index") != i) {
          $(this).trigger("scroller.beforescroll", [item, instant]);

          $(this).data("scroller-index", i);
          $(this).scrollerUpdate(instant);
        }
      
      }
      
    });
  
    return $(this);
  };

  $.fn.scrollerPrevious = function(instant) {
 
   $(this).each( function() {

     if (!$(this).data("scroller-animating") && !$(this).data("scroller-disabled")) {

       var s = $(this).data("scroller-settings");
       var item = $(s.itemSelector + ':eq(' + $(this).data("scroller-index") + ')', $(this));


       if ($(this).data("scroller-index") > 0) {
         $(this).trigger("scroller.beforescrollprevious", [item]);
         $(this).trigger("scroller.beforescroll", [item]);

         $(this).data("scroller-index", $(this).data("scroller-index") - 1);

         $(this).scrollerUpdate(instant);
       }
  
    }
   });
  
   return $(this);
  };
 
 
})(jQuery);