;(function ($, window, document, undefined) {

'use strict';

Tennpipes.libs.tab = {
  name : 'tab',

  version : '5.5.1',

  settings : {
    active_class : 'active',
    callback : function () {},
    deep_linking : false,
    scroll_to_content : true,
    is_hover : false
  },

  default_tab_hashes : [],

  init : function (scope, method, options) {
    var self = this,
        S = this.S;

    this.bindings(method, options);

    // store the initial href, which is used to allow correct behaviour of the
    // browser back button when deep linking is turned on.
    self.entry_location = window.location.href;

    this.handle_location_hash_change();

    // Store the default active tabs which will be referenced when the
    // location hash is absent, as in the case of navigating the tabs and
    // returning to the first viewing via the browser Back button.
    S('[' + this.attr_name() + '] > .active > a', this.scope).each(function () {
      self.default_tab_hashes.push(this.hash);
    });
  },

  events : function () {
    var self = this,
        S = this.S;

    var usual_tab_behavior =  function (e) {
        var settings = S(this).closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init');
        if (!settings.is_hover || Modernizr.touch) {
          e.preventDefault();
          e.stopPropagation();
          self.toggle_active_tab(S(this).parent());
        }
      };

    S(this.scope)
      .off('.tab')
      // Click event: tab title
      .on('focus.fndtn.tab', '[' + this.attr_name() + '] > * > a', usual_tab_behavior )
      .on('click.fndtn.tab', '[' + this.attr_name() + '] > * > a', usual_tab_behavior )
      // Hover event: tab title
      .on('mouseenter.fndtn.tab', '[' + this.attr_name() + '] > * > a', function (e) {
        var settings = S(this).closest('[' + self.attr_name() + ']').data(self.attr_name(true) + '-init');
        if (settings.is_hover) {
          self.toggle_active_tab(S(this).parent());
        }
      });

    // Location hash change event
    S(window).on('hashchange.fndtn.tab', function (e) {
      e.preventDefault();
      self.handle_location_hash_change();
    });
  },

  handle_location_hash_change : function () {

    var self = this,
        S = this.S;

    S('[' + this.attr_name() + ']', this.scope).each(function () {
      var settings = S(this).data(self.attr_name(true) + '-init');
      if (settings.deep_linking) {
        // Match the location hash to a label
        var hash;
        if (settings.scroll_to_content) {
          hash = self.scope.location.hash;
        } else {
          // prefix the hash to prevent anchor scrolling
          hash = self.scope.location.hash.replace('fndtn-', '');
        }
        if (hash != '') {
          // Check whether the location hash references a tab content div or
          // another element on the page (inside or outside the tab content div)
          var hash_element = S(hash);
          if (hash_element.hasClass('content') && hash_element.parent().hasClass('tabs-content')) {
            // Tab content div
            self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + hash + ']').parent());
          } else {
            // Not the tab content div. If inside the tab content, find the
            // containing tab and toggle it as active.
            var hash_tab_container_id = hash_element.closest('.content').attr('id');
            if (hash_tab_container_id != undefined) {
              self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=#' + hash_tab_container_id + ']').parent(), hash);
            }
          }
        } else {
          // Reference the default tab hashes which were initialized in the init function
          for (var ind = 0; ind < self.default_tab_hashes.length; ind++) {
            self.toggle_active_tab($('[' + self.attr_name() + '] > * > a[href=' + self.default_tab_hashes[ind] + ']').parent());
          }
        }
      }
     });
   },

  toggle_active_tab : function (tab, location_hash) {
    var self = this,
        S = self.S,
        tabs = tab.closest('[' + this.attr_name() + ']'),
        tab_link = tab.find('a'),
        anchor = tab.children('a').first(),
        target_hash = '#' + anchor.attr('href').split('#')[1],
        target = S(target_hash),
        siblings = tab.siblings(),
        settings = tabs.data(this.attr_name(true) + '-init'),
        interpret_keyup_action = function (e) {
          // Light modification of Heydon Pickering's Practical ARIA Examples: http://heydonworks.com/practical_aria_examples/js/a11y.js

          // define current, previous and next (possible) tabs

          var $original = $(this);
          var $prev = $(this).parents('li').prev().children('[role="tab"]');
          var $next = $(this).parents('li').next().children('[role="tab"]');
          var $target;

          // find the direction (prev or next)

          switch (e.keyCode) {
            case 37:
              $target = $prev;
              break;
            case 39:
              $target = $next;
              break;
            default:
              $target = false
                break;
          }

          if ($target.length) {
            $original.attr({
              'tabindex' : '-1',
              'aria-selected' : null
            });
            $target.attr({
              'tabindex' : '0',
              'aria-selected' : true
            }).focus();
          }

          // Hide panels

          $('[role="tabpanel"]')
            .attr('aria-hidden', 'true');

          // Show panel which corresponds to target

          $('#' + $(document.activeElement).attr('href').substring(1))
            .attr('aria-hidden', null);

        },
        go_to_hash = function(hash) {
          // This function allows correct behaviour of the browser's back button when deep linking is enabled. Without it
          // the user would get continually redirected to the default hash.
          var is_entry_location = window.location.href === self.entry_location,
              default_hash = settings.scroll_to_content ? self.default_tab_hashes[0] : is_entry_location ? window.location.hash :'fndtn-' + self.default_tab_hashes[0].replace('#', '')

          if (!(is_entry_location && hash === default_hash)) {
            window.location.hash = hash;
          }
        };

    // allow usage of data-tab-content attribute instead of href
    if (S(this).data(this.data_attr('tab-content'))) {
      target_hash = '#' + S(this).data(this.data_attr('tab-content')).split('#')[1];
      target = S(target_hash);
    }

    if (settings.deep_linking) {

      if (settings.scroll_to_content) {

        // retain current hash to scroll to content
        go_to_hash(location_hash || target_hash);

        if (location_hash == undefined || location_hash == target_hash) {
          tab.parent()[0].scrollIntoView();
        } else {
          S(target_hash)[0].scrollIntoView();
        }
      } else {
        // prefix the hashes so that the browser doesn't scroll down
        if (location_hash != undefined) {
          go_to_hash('fndtn-' + location_hash.replace('#', ''));
        } else {
          go_to_hash('fndtn-' + target_hash.replace('#', ''));
        }
      }
    }

    // WARNING: The activation and deactivation of the tab content must
    // occur after the deep linking in order to properly refresh the browser
    // window (notably in Chrome).
    // Clean up multiple attr instances to done once
    tab.addClass(settings.active_class).triggerHandler('opened');
    tab_link.attr({'aria-selected' : 'true',  tabindex : 0});
    siblings.removeClass(settings.active_class)
    siblings.find('a').attr({'aria-selected' : 'false',  tabindex : -1});
    target.siblings().removeClass(settings.active_class).attr({'aria-hidden' : 'true',  tabindex : -1});
    target.addClass(settings.active_class).attr('aria-hidden', 'false').removeAttr('tabindex');
    settings.callback(tab);
    target.triggerHandler('toggled', [tab]);
    tabs.triggerHandler('toggled', [target]);

    tab_link.off('keydown').on('keydown', interpret_keyup_action );
  },

  data_attr : function (str) {
    if (this.namespace.length > 0) {
      return this.namespace + '-' + str;
    }

    return str;
  },

  off : function () {},

  reflow : function () {}
};

}(jQuery, window, window.document));