// Scroll Animations

AOS.init();

// Number counter

(function ($) {
	$.fn.countTo = function (options) {
		options = options || {};

		return $(this).each(function () {
			// set options for current element
			var settings = $.extend({}, $.fn.countTo.defaults, {
				from:            $(this).data('from'),
				to:              $(this).data('to'),
				speed:           $(this).data('speed'),
				refreshInterval: $(this).data('refresh-interval'),
				decimals:        $(this).data('decimals')
			}, options);

			// how many times to update the value, and how much to increment the value on each update
			var loops = Math.ceil(settings.speed / settings.refreshInterval),
				increment = (settings.to - settings.from) / loops;

			// references & variables that will change with each update
			var self = this,
				$self = $(this),
				loopCount = 0,
				value = settings.from,
				data = $self.data('countTo') || {};

			$self.data('countTo', data);

			// if an existing interval can be found, clear it first
			if (data.interval) {
				clearInterval(data.interval);
			}
			data.interval = setInterval(updateTimer, settings.refreshInterval);

			// initialize the element with the starting value
			render(value);

			function updateTimer() {
				value += increment;
				loopCount++;

				render(value);

				if (typeof(settings.onUpdate) == 'function') {
					settings.onUpdate.call(self, value);
				}

				if (loopCount >= loops) {
					// remove the interval
					$self.removeData('countTo');
					clearInterval(data.interval);
					value = settings.to;

					if (typeof(settings.onComplete) == 'function') {
						settings.onComplete.call(self, value);
					}
				}
			}

			function render(value) {
				var formattedValue = settings.formatter.call(self, value, settings);
				$self.html(formattedValue);
			}
		});
	};

	$.fn.countTo.defaults = {
		from: 0,               // the number the element should start at
		to: 0,                 // the number the element should end at
		speed: 1000,           // how long it should take to count between the target numbers
		refreshInterval: 100,  // how often the element should be updated
		decimals: 0,           // the number of decimal places to show
		formatter: formatter,  // handler for formatting the value before rendering
		onUpdate: null,        // callback method for every time the element is updated
		onComplete: null       // callback method for when the element finishes updating
	};

	function formatter(value, settings) {
		return value.toFixed(settings.decimals);
	}
}(jQuery));

jQuery(function ($) {
  // custom formatting example
  $('.count-number').data('countToOptions', {
	formatter: function (value, options) {
	  return value.toFixed(options.decimals).replace(/\B(?=(?:\d{3})+(?!\d))/g, ',');
	}
  });

  // start all the timers
  $('.timer').each(count);

  function count(options) {
	var $this = $(this);
	options = $.extend({}, options || {}, $this.data('countToOptions') || {});
	$this.countTo(options);
  }
});

// preloader

(function(loader) {

  window.addEventListener('beforeunload', function(e) {
    activateLoader();
  });

  window.addEventListener('load', function(e) {
    deactivateLoader();
  });

  function activateLoader() {
    loader.style.display = 'block';
    loader.style.opacity = 1;
  }

  function deactivateLoader() {
    /**
     * ensures that the loading animation plays for at least a second to give the
     * appearance of seamless loading on pages that execute and load extremely
     * quickly (i.e., intranet pages)
     */
    setTimeout(function() {
      deactivate();
    }, 1500);

    function deactivate() {
      loader.style.opacity = 0;
      loader.addEventListener('transitionend', function() {
        loader.style.display = 'none';
      }, false);
    }
  }

})(document.querySelector('.o-page-loader'));

// Inline scroll

var toc = document.querySelector( '.toc' );
var tocPath = document.querySelector( '.toc-marker path' );
var tocItems;

// Factor of screen size that the element must cross
// before it's considered visible
var TOP_MARGIN = 0.1,
		BOTTOM_MARGIN = 0.2;

var pathLength;

var lastPathStart,
		lastPathEnd;

window.addEventListener( 'resize', drawPath, false );
window.addEventListener( 'scroll', sync, false );

drawPath();

function drawPath() {

	tocItems = [].slice.call( toc.querySelectorAll( 'li' ) );

	// Cache element references and measurements
	tocItems = tocItems.map( function( item ) {
		var anchor = item.querySelector( 'a' );
		var target = document.getElementById( anchor.getAttribute( 'href' ).slice( 1 ) );

		return {
			listItem: item,
			anchor: anchor,
			target: target
		};
	} );

	// Remove missing targets
	tocItems = tocItems.filter( function( item ) {
		return !!item.target;
	} );

	var path = [];
	var pathIndent;

	tocItems.forEach( function( item, i ) {

		var x = item.anchor.offsetLeft - 5,
				y = item.anchor.offsetTop,
				height = item.anchor.offsetHeight;

		if( i === 0 ) {
			path.push( 'M', x, y, 'L', x, y + height );
			item.pathStart = 0;
		}
		else {
			// Draw an additional line when there's a change in
			// indent levels
			if( pathIndent !== x ) path.push( 'L', pathIndent, y );

			path.push( 'L', x, y );

			// Set the current path so that we can measure it
			tocPath.setAttribute( 'd', path.join( ' ' ) );
			item.pathStart = tocPath.getTotalLength() || 0;

			path.push( 'L', x, y + height );
		}

		pathIndent = x;

		tocPath.setAttribute( 'd', path.join( ' ' ) );
		item.pathEnd = tocPath.getTotalLength();

	} );

	pathLength = tocPath.getTotalLength();

	sync();

}

function sync() {

	var windowHeight = window.innerHeight;

	var pathStart = pathLength,
			pathEnd = 0;

	var visibleItems = 0;

	tocItems.forEach( function( item ) {

		var targetBounds = item.target.getBoundingClientRect();

		if( targetBounds.bottom > windowHeight * TOP_MARGIN && targetBounds.top < windowHeight * ( 1 - BOTTOM_MARGIN ) ) {
			pathStart = Math.min( item.pathStart, pathStart );
			pathEnd = Math.max( item.pathEnd, pathEnd );

			visibleItems += 1;

			item.listItem.classList.add( 'visible' );
		}
		else {
			item.listItem.classList.remove( 'visible' );
		}

	} );

	// Specify the visible path or hide the path altogether
	// if there are no visible items
	if( visibleItems > 0 && pathStart < pathEnd ) {
		if( pathStart !== lastPathStart || pathEnd !== lastPathEnd ) {
			tocPath.setAttribute( 'stroke-dashoffset', '1' );
			tocPath.setAttribute( 'stroke-dasharray', '1, '+ pathStart +', '+ ( pathEnd - pathStart ) +', ' + pathLength );
			tocPath.setAttribute( 'opacity', 1 );
		}
	}
	else {
		tocPath.setAttribute( 'opacity', 0 );
	}

	lastPathStart = pathStart;
	lastPathEnd = pathEnd;

}
