/**
 * Addons for WPBakery - Counter animation.
 *
 * Counts each .cafw-counter__value from its data-start up to its data-target
 * when it scrolls into view. Respects prefers-reduced-motion and degrades to the
 * final value if IntersectionObserver is unavailable.
 */
( function () {
	'use strict';

	function fractionDigits( str ) {
		var i = ( str || '' ).indexOf( '.' );
		return -1 === i ? 0 : Math.min( str.length - i - 1, 20 );
	}

	function animate( el ) {
		var rawTarget = el.getAttribute( 'data-target' ) || '';
		var rawStart = el.getAttribute( 'data-start' ) || '0';
		var target = parseFloat( rawTarget ) || 0;
		var start = parseFloat( rawStart ) || 0;
		var duration = parseInt( el.getAttribute( 'data-duration' ), 10 ) || 2000;
		// Keep as many decimals as the most precise of start / end (e.g. "3.14" -> 2).
		var decimals = Math.max( fractionDigits( rawTarget ), fractionDigits( rawStart ) );
		var startTime = null;

		function format( value ) {
			return value.toLocaleString( undefined, {
				minimumFractionDigits: decimals,
				maximumFractionDigits: decimals,
			} );
		}

		function step( timestamp ) {
			if ( null === startTime ) {
				startTime = timestamp;
			}
			var progress = Math.min( ( timestamp - startTime ) / duration, 1 );
			// easeOutCubic for a natural finish.
			var eased = 1 - Math.pow( 1 - progress, 3 );
			el.textContent = format( start + ( target - start ) * eased );
			if ( progress < 1 ) {
				window.requestAnimationFrame( step );
			} else {
				el.textContent = format( target );
			}
		}

		window.requestAnimationFrame( step );
	}

	function init() {
		var counters = document.querySelectorAll( '.cafw-counter__value' );
		if ( ! counters.length ) {
			return;
		}

		var reduceMotion = window.matchMedia && window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches;

		if ( reduceMotion || ! ( 'IntersectionObserver' in window ) ) {
			counters.forEach( function ( el ) {
				var target = parseFloat( el.getAttribute( 'data-target' ) ) || 0;
				el.textContent = target.toLocaleString();
			} );
			return;
		}

		var observer = new IntersectionObserver(
			function ( entries, obs ) {
				entries.forEach( function ( entry ) {
					if ( entry.isIntersecting ) {
						animate( entry.target );
						obs.unobserve( entry.target );
					}
				} );
			},
			{ threshold: 0.4 }
		);

		counters.forEach( function ( el ) {
			observer.observe( el );
		} );
	}

	if ( 'loading' === document.readyState ) {
		document.addEventListener( 'DOMContentLoaded', init );
	} else {
		init();
	}
} )();
