/*!
 * jQuery twitter bootstrap wizard plugin
 * Examples and documentation at: http://github.com/VinceG/twitter-bootstrap-wizard
 * version 1.4.2
 * Requires jQuery v1.3.2 or later
 * Supports Bootstrap 2.2.x, 2.3.x, 3.0
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * Authors: Vadim Vincent Gabriel (http://vadimg.com), Jason Gill (www.gilluminate.com)
 */
;
(function($) {
  var bootstrapWizardCreate = function(element, options) {
    var element = $(element);
    var obj = this;

    // selector skips any 'li' elements that do not contain a child with a tab data-toggle
    var baseItemSelector = 'li:has([data-toggle="tab"])';
    var historyStack = [];

    // Merge options with defaults
    var $settings = $.extend({}, $.fn.bootstrapWizard.defaults, options);
    var $activeTab = null;
    var $navigation = null;

    this.rebindClick = function(selector, fn) {
      selector.unbind('click', fn).bind('click', fn);
    }

    this.fixNavigationButtons = function() {
      // Get the current active tab
      if (!$activeTab.length) {
        // Select first one
        $navigation.find('a:first').tab('show');
        $activeTab = $navigation.find(baseItemSelector + ':first');
      }

      // See if we're currently in the first/last then disable the previous and last buttons
      $($settings.previousSelector, element).toggleClass('disabled', (obj.firstIndex() >= obj.currentIndex()));
      $($settings.nextSelector, element).toggleClass('disabled', (obj.currentIndex() >= obj.navigationLength()));
      $($settings.nextSelector, element).toggleClass('hidden', (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));
      $($settings.lastSelector, element).toggleClass('hidden', (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));
      $($settings.finishSelector, element).toggleClass('hidden', (obj.currentIndex() < obj.navigationLength()));
      $($settings.backSelector, element).toggleClass('disabled', (historyStack.length == 0));
      $($settings.backSelector, element).toggleClass('hidden', (obj.currentIndex() >= obj.navigationLength() && $($settings.finishSelector, element).length > 0));

      // We are unbinding and rebinding to ensure single firing and no double-click errors
      obj.rebindClick($($settings.nextSelector, element), obj.next);
      obj.rebindClick($($settings.previousSelector, element), obj.previous);
      obj.rebindClick($($settings.lastSelector, element), obj.last);
      obj.rebindClick($($settings.firstSelector, element), obj.first);
      obj.rebindClick($($settings.finishSelector, element), obj.finish);
      obj.rebindClick($($settings.backSelector, element), obj.back);

      if ($settings.onTabShow && typeof $settings.onTabShow === 'function' && $settings.onTabShow($activeTab, $navigation, obj.currentIndex()) === false) {
        return false;
      }
    };

    this.next = function(e) {
      // If we clicked the last then dont activate this
      if (element.hasClass('last')) {
        return false;
      }

      if ($settings.onNext && typeof $settings.onNext === 'function' && $settings.onNext($activeTab, $navigation, obj.nextIndex()) === false) {
        return false;
      }

      var formerIndex = obj.currentIndex();
      var $index = obj.nextIndex();

      // Did we click the last button
      if ($index > obj.navigationLength()) {} else {
        historyStack.push(formerIndex);
        $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '') + ':eq(' + $index + ') a').tab('show');
      }
    };

    this.previous = function(e) {
      // If we clicked the first then dont activate this
      if (element.hasClass('first')) {
        return false;
      }

      if ($settings.onPrevious && typeof $settings.onPrevious === 'function' && $settings.onPrevious($activeTab, $navigation, obj.previousIndex()) === false) {
        return false;
      }

      var formerIndex = obj.currentIndex();
      var $index = obj.previousIndex();

      if ($index < 0) {} else {
        historyStack.push(formerIndex);
        $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '') + ':eq(' + $index + ') a').tab('show');
      }
    };

    this.first = function(e) {
      if ($settings.onFirst && typeof $settings.onFirst === 'function' && $settings.onFirst($activeTab, $navigation, obj.firstIndex()) === false) {
        return false;
      }

      // If the element is disabled then we won't do anything
      if (element.hasClass('disabled')) {
        return false;
      }


      historyStack.push(obj.currentIndex());
      $navigation.find(baseItemSelector + ':eq(0) a').tab('show');
    };

    this.last = function(e) {
      if ($settings.onLast && typeof $settings.onLast === 'function' && $settings.onLast($activeTab, $navigation, obj.lastIndex()) === false) {
        return false;
      }

      // If the element is disabled then we won't do anything
      if (element.hasClass('disabled')) {
        return false;
      }

      historyStack.push(obj.currentIndex());
      $navigation.find(baseItemSelector + ':eq(' + obj.navigationLength() + ') a').tab('show');
    };

    this.finish = function(e) {
      if ($settings.onFinish && typeof $settings.onFinish === 'function') {
        $settings.onFinish($activeTab, $navigation, obj.lastIndex());
      }
    };

    this.back = function() {
      if (historyStack.length == 0) {
        return null;
      }

      var formerIndex = historyStack.pop();
      if ($settings.onBack && typeof $settings.onBack === 'function' && $settings.onBack($activeTab, $navigation, formerIndex) === false) {
        historyStack.push(formerIndex);
        return false;
      }

      element.find(baseItemSelector + ':eq(' + formerIndex + ') a').tab('show');
    };

    this.currentIndex = function() {
      return $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '')).index($activeTab);
    };

    this.firstIndex = function() {
      return 0;
    };

    this.lastIndex = function() {
      return obj.navigationLength();
    };

    this.getIndex = function(e) {
      return $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '')).index(e);
    };

    this.nextIndex = function() {
      var nextIndexCandidate = this.currentIndex();
      var nextTabCandidate = null;
      do {
        nextIndexCandidate++;
        nextTabCandidate = $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '') + ":eq(" + nextIndexCandidate + ")");
      } while ((nextTabCandidate) && (nextTabCandidate.hasClass("disabled")));
      return nextIndexCandidate;
    };
    this.previousIndex = function() {
      var prevIndexCandidate = this.currentIndex();
      var prevTabCandidate = null;
      do {
        prevIndexCandidate--;
        prevTabCandidate = $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '') + ":eq(" + prevIndexCandidate + ")");
      } while ((prevTabCandidate) && (prevTabCandidate.hasClass("disabled")));
      return prevIndexCandidate;
    };
    this.navigationLength = function() {
      return $navigation.find(baseItemSelector + ($settings.withVisible ? ':visible' : '')).length - 1;
    };
    this.activeTab = function() {
      return $activeTab;
    };
    this.nextTab = function() {
      return $navigation.find(baseItemSelector + ':eq(' + (obj.currentIndex() + 1) + ')').length ? $navigation.find(baseItemSelector + ':eq(' + (obj.currentIndex() + 1) + ')') : null;
    };
    this.previousTab = function() {
      if (obj.currentIndex() <= 0) {
        return null;
      }
      return $navigation.find(baseItemSelector + ':eq(' + parseInt(obj.currentIndex() - 1) + ')');
    };
    this.show = function(index) {
      var tabToShow = isNaN(index) ?
        element.find(baseItemSelector + ' a[href="#' + index + '"]') :
        element.find(baseItemSelector + ':eq(' + index + ') a');
      if (tabToShow.length > 0) {
        historyStack.push(obj.currentIndex());
        tabToShow.tab('show');
      }
    };
    this.disable = function(index) {
      $navigation.find(baseItemSelector + ':eq(' + index + ')').addClass('disabled');
    };
    this.enable = function(index) {
      $navigation.find(baseItemSelector + ':eq(' + index + ')').removeClass('disabled');
    };
    this.hide = function(index) {
      $navigation.find(baseItemSelector + ':eq(' + index + ')').hide();
    };
    this.display = function(index) {
      $navigation.find(baseItemSelector + ':eq(' + index + ')').show();
    };
    this.remove = function(args) {
      var $index = args[0];
      var $removeTabPane = typeof args[1] != 'undefined' ? args[1] : false;
      var $item = $navigation.find(baseItemSelector + ':eq(' + $index + ')');

      // Remove the tab pane first if needed
      if ($removeTabPane) {
        var $href = $item.find('a').attr('href');
        $($href).remove();
      }

      // Remove menu item
      $item.remove();
    };

    var innerTabClick = function(e) {
      // Get the index of the clicked tab
      var $ul = $navigation.find(baseItemSelector);
      var clickedIndex = $ul.index($(e.currentTarget).parent(baseItemSelector));
      var $clickedTab = $($ul[clickedIndex]);
      if ($settings.onTabClick && typeof $settings.onTabClick === 'function' && $settings.onTabClick($activeTab, $navigation, obj.currentIndex(), clickedIndex, $clickedTab) === false) {
        return false;
      }
    };

    var innerTabShown = function(e) {
      var $element = $(e.target).parent();
      var nextTab = $navigation.find(baseItemSelector).index($element);

      // If it's disabled then do not change
      if ($element.hasClass('disabled')) {
        return false;
      }

      if ($settings.onTabChange && typeof $settings.onTabChange === 'function' && $settings.onTabChange($activeTab, $navigation, obj.currentIndex(), nextTab) === false) {
        return false;
      }

      $activeTab = $element; // activated tab
      obj.fixNavigationButtons();
    };

    this.resetWizard = function() {

      // remove the existing handlers
      $('a[data-toggle="tab"]', $navigation).off('click', innerTabClick);
      $('a[data-toggle="tab"]', $navigation).off('show show.bs.tab', innerTabShown);

      // reset elements based on current state of the DOM
      $navigation = element.find('ul:first', element);
      $activeTab = $navigation.find(baseItemSelector + '.active', element);

      // re-add handlers
      $('a[data-toggle="tab"]', $navigation).on('click', innerTabClick);
      $('a[data-toggle="tab"]', $navigation).on('show show.bs.tab', innerTabShown);

      obj.fixNavigationButtons();
    };

    $navigation = element.find('ul:first', element);
    $activeTab = $navigation.find(baseItemSelector + '.active', element);

    if (!$navigation.hasClass($settings.tabClass)) {
      $navigation.addClass($settings.tabClass);
    }

    // Load onInit
    if ($settings.onInit && typeof $settings.onInit === 'function') {
      $settings.onInit($activeTab, $navigation, 0);
    }

    // Load onShow
    if ($settings.onShow && typeof $settings.onShow === 'function') {
      $settings.onShow($activeTab, $navigation, obj.nextIndex());
    }

    $('a[data-toggle="tab"]', $navigation).on('click', innerTabClick);

    // attach to both show and show.bs.tab to support Bootstrap versions 2.3.2 and 3.0.0
    $('a[data-toggle="tab"]', $navigation).on('show show.bs.tab', innerTabShown);
  };
  $.fn.bootstrapWizard = function(options) {
    //expose methods
    if (typeof options == 'string') {
      var args = Array.prototype.slice.call(arguments, 1)
      if (args.length === 1) {
        args.toString();
      }
      return this.data('bootstrapWizard')[options](args);
    }
    return this.each(function(index) {
      var element = $(this);
      // Return early if this element already has a plugin instance
      if (element.data('bootstrapWizard')) return;
      // pass options to plugin constructor
      var wizard = new bootstrapWizardCreate(element, options);
      // Store plugin object in this element's data
      element.data('bootstrapWizard', wizard);
      // and then trigger initial change
      wizard.fixNavigationButtons();
    });
  };

  // expose options
  $.fn.bootstrapWizard.defaults = {
    withVisible: true,
    tabClass: 'nav nav-pills',
    nextSelector: '.card-wizard .nav-item.next',
    previousSelector: '.card-wizard .nav-item.previous',
    firstSelector: '.card-wizard .nav-item.first',
    lastSelector: '.card-wizard .nav-item.last',
    finishSelector: '.card-wizard .nav-item.finish',
    backSelector: '.card-wizard .nav-item.back',
    onShow: null,
    onInit: null,
    onNext: null,
    onPrevious: null,
    onLast: null,
    onFirst: null,
    onFinish: null,
    onBack: null,
    onTabChange: null,
    onTabClick: null,
    onTabShow: null
  };

})(jQuery);