/**

* HSScrollNav Component.
*
* @author Htmlstream
* @version 1.0
* @requires jQuery
*
*/

;(function ($) {

'use strict';

$.HSCore.components.HSScrollNav = {

  /**
   * Base configuraion of the component.
   *
   * @private
   */
  _baseConfig: {
    duration: 400,
    easing: 'linear',
    over: $(),
    activeItemClass: 'active',
    afterShow: function(){},
    beforeShow: function(){}
  },

  /**
   * All initialized item on the page.
   *
   * @private
   */
  _pageCollection: $(),

  /**
   * Initialization of the component.
   *
   * @param {jQuery} collection
   * @param {Object} config
   *
   * @public
   * @return {jQuery}
   */
  init: function(collection, config) {

    var self = this;

    if( !collection || !collection.length ) return $();

    collection.each(function(i, el) {

      var $this = $(el),
          itemConfig = config && $.isPlainObject(config) ?
                       $.extend(true, {}, self._baseConfig, config, $this.data()) :
                       $.extend(true, {}, self._baseConfig, $this.data());

      if( !$this.data('HSScrollNav') ) {

        $this.data('HSScrollNav', new HSScrollNav($this, itemConfig));

        self._pageCollection = self._pageCollection.add( $this );

      }

    });

    $(window).on('scroll.HSScrollNav', function(){

      self._pageCollection.each(function(i, el) {

        $(el).data('HSScrollNav').highlight();

      });

    }).trigger('scroll.HSScrollNav');

    return collection;

  }

}

/**
 * HSScrollNav.
 *
 * @param {jQuery} element
 * @param {Object} config
 *
 * @constructor
 */
function HSScrollNav(element, config) {

  /**
   * Current element.
   *
   * @public
   */
  this.element = element;

  /**
   * Configuraion.
   *
   * @public
   */
  this.config = config;

  /**
   * Sections.
   *
   * @public
   */
  this._items = $();

  this._makeItems();
  this._bindEvents();
}

/**
 * Return collection of sections.
 *
 * @private
 * @return {jQuery}
 */
HSScrollNav.prototype._makeItems = function() {

  var self = this;

  this.element.find('a[href^="#"]').each(function(i, el) {

    var $this = $(el);

    if( !$this.data('HSScrollNavSection') ) {

      $this.data('HSScrollNavSection', new HSScrollNavSection($this, self.config));

      self._items = self._items.add( $this );

    }

  });

};

/**
 * Binds necessary events.
 *
 * @private
 * @return {undefined}
 */
HSScrollNav.prototype._bindEvents = function() {

  var self = this;

  this.element.on('click.HSScrollNav', 'a[href^="#"]', function(e) {

    var link = this;
    self._lockHightlight = true;
    if(self.current) self.current.unhighlight();
    link.blur();
    self.current = $(link).data('HSScrollNavSection');
    self.current.highlight();

    $(this).data('HSScrollNavSection').show( function(){
      self._lockHightlight = false;
    } );

    e.preventDefault();

  });

};

/**
 * Activates necessary menu item.
 *
 * @public
 */
HSScrollNav.prototype.highlight = function() {

  var self = this, items, currentItem, current, scrollTop;

  if(!this._items.length || this._lockHightlight) return;

  scrollTop = $(window).scrollTop();

  if(scrollTop + $(window).height() === $(document).height()) {

    this.current = this._items.last().data('HSScrollNavSection');

    this.unhighlight();
    this.current.highlight();
    this.current.changeHash();

    return;
  }

  this._items.each(function(i, el){

    var Section = $(el).data('HSScrollNavSection'),
        $section = Section.section;

    if(scrollTop > Section.offset) {
      current = Section;
    }

  });

  if(current && this.current != current) {

    this.unhighlight();
    current.highlight();
    if(this.current) current.changeHash();

    this.current = current;

  }

};

/**
 * Deactivates all menu items.
 *
 * @public
 */
HSScrollNav.prototype.unhighlight = function() {

  this._items.each(function(i, el){
    $(el).data('HSScrollNavSection').unhighlight();
  });

};

/**
 * HSScrollNavSection.
 *
 * @param {jQuery} element
 *
 * @constructor
 */
function HSScrollNavSection(element, config) {

  var self = this;

  /**
   * Current section.
   *
   * @public
   */
  this.element = element;

  /**
   * Configuration.
   *
   * @public
   */
  this.config = config;

  /**
   * Getter for acces to the section element.
   *
   * @public
   */
  Object.defineProperty(this, 'section', {
    value: $(self.element.attr('href'))
  });

  /**
   * Getter for determinate position of the section relative to document.
   *
   * @public
   */

  Object.defineProperty(this, 'offset', {
    get: function() {

      var header = $('.u-header'),
          headerStyles = getComputedStyle(header.get(0)),
          headerPosition = headerStyles.position,
          offset = self.section.offset().top;

      if(header.length && headerPosition == 'fixed' && parseInt(headerStyles.top) == 0) {
        offset = offset - header.outerHeight() - parseInt(headerStyles.marginTop);
      }

      if(self.config.over.length) {
        offset = offset - self.config.over.outerHeight();
      }

      return offset;
    }
  });

}

/**
 * Moves to the section.
 *
 * @public
 */
HSScrollNavSection.prototype.show = function(callback) {

  var self = this;

  if( !this.section.length ) return;

  self.config.beforeShow.call(self.section);

  this.changeHash();

  $('html, body').stop().animate({
    scrollTop: self.offset + 3
  }, {
    duration: self.config.duration,
    easing: self.config.easing,
    complete: function() {
      $('html, body').stop().animate({
        scrollTop: self.offset + 3
      }, {
        duration: self.config.duration,
        easing: self.config.easing,
        complete: function() {
          self.config.afterShow.call(self.section);
          if($.isFunction(callback)) callback();
        }
      });
    }
  });

};

/**
 * Changes location's hash.
 *
 * @public
 */
HSScrollNavSection.prototype.changeHash = function() {
  this.section.attr('id', '');
  window.location.hash = this.element.attr('href');
  this.section.attr('id', this.element.attr('href').slice(1));
};

/**
 * Activates the menu item.
 *
 * @public
 */
HSScrollNavSection.prototype.highlight = function() {

  var parent = this.element.parent('li');
  if(parent.length) parent.addClass(this.config.activeItemClass);

};

/**
 * Deactivates the menu item.
 *
 * @public
 */
HSScrollNavSection.prototype.unhighlight = function() {

  var parent = this.element.parent('li');
  if(parent.length) parent.removeClass(this.config.activeItemClass);

};

})(jQuery);