/*!
 * Themecut UI Library
 * Scroll animations (fade, stagger, counter) + Feather icon init.
 * No dependencies. Vanilla JS, IntersectionObserver API.
 */
(function () {
	'use strict';

	/* -------------------------------------------------------------------------
	   Config
	------------------------------------------------------------------------- */
	var TC = window.TC = window.TC || {};

	var FADE_DURATION  = 600;   // ms
	var STAGGER_DELAY  = 80;    // ms per child
	var COUNTER_DURATION = 1800; // ms
	var IO_THRESHOLD   = 0.15;  // 15% visible triggers

	/* -------------------------------------------------------------------------
	   Utility
	------------------------------------------------------------------------- */
	function easeOut(t) {
		return 1 - Math.pow(1 - t, 3);
	}

	function parseNumber(str) {
		// Strip non-numeric suffixes like "+" "%" "k" "K"
		return parseFloat(str.replace(/[^0-9.]/g, '')) || 0;
	}

	function getSuffix(str) {
		var match = str.match(/[^0-9.]+$/);
		return match ? match[0] : '';
	}

	function getPrefix(str) {
		var match = str.match(/^[^0-9.]*/);
		return match && match[0] !== '' ? match[0] : '';
	}

	/* -------------------------------------------------------------------------
	   Fade / slide animations
	   Usage: add class tc-fade, tc-fade-up, tc-fade-down, tc-fade-left, tc-fade-right
	------------------------------------------------------------------------- */
	function initFade() {
		var els = document.querySelectorAll('.tc-fade, .tc-fade-up, .tc-fade-down, .tc-fade-left, .tc-fade-right');
		if (!els.length) return;

		var observer = new IntersectionObserver(function (entries) {
			entries.forEach(function (entry) {
				if (entry.isIntersecting) {
					entry.target.classList.add('tc-visible');
					observer.unobserve(entry.target);
				}
			});
		}, { threshold: IO_THRESHOLD });

		els.forEach(function (el) {
			el.classList.add('tc-hidden');
			var dir = el.classList.contains('tc-fade-left')  ? 'left'
			        : el.classList.contains('tc-fade-right') ? 'right'
			        : el.classList.contains('tc-fade-down')  ? 'down'
			        : 'up';
			el.setAttribute('data-tc-dir', dir);
			observer.observe(el);
		});
	}

	/* -------------------------------------------------------------------------
	   Stagger — applies tc-hidden + staggered delay to direct children
	   Usage: add class tc-stagger to a grid/flex container
	------------------------------------------------------------------------- */
	function initStagger() {
		var containers = document.querySelectorAll('.tc-stagger');
		if (!containers.length) return;

		var observer = new IntersectionObserver(function (entries) {
			entries.forEach(function (entry) {
				if (!entry.isIntersecting) return;
				var children = entry.target.children;
				Array.from(children).forEach(function (child, i) {
					setTimeout(function () {
						child.classList.add('tc-visible');
					}, i * STAGGER_DELAY);
				});
				observer.unobserve(entry.target);
			});
		}, { threshold: IO_THRESHOLD });

		containers.forEach(function (container) {
			Array.from(container.children).forEach(function (child) {
				child.classList.add('tc-hidden');
				child.setAttribute('data-tc-dir', 'up');
			});
			observer.observe(container);
		});
	}

	/* -------------------------------------------------------------------------
	   Counter — animates a number from 0 to its text value
	   Usage: data-tc-counter on a paragraph or heading
	   Preserves prefix ("$") and suffix ("+", "%", "k", "M")
	------------------------------------------------------------------------- */
	function animateCounter(el) {
		var raw    = el.textContent.trim();
		var target = parseNumber(raw);
		var suffix = getSuffix(raw);
		var prefix = getPrefix(raw);
		var start  = null;

		if (!target) return;

		function step(timestamp) {
			if (!start) start = timestamp;
			var progress = Math.min((timestamp - start) / COUNTER_DURATION, 1);
			var current  = Math.round(easeOut(progress) * target);
			el.textContent = prefix + current.toLocaleString() + suffix;
			if (progress < 1) requestAnimationFrame(step);
		}

		requestAnimationFrame(step);
	}

	function initCounters() {
		var els = document.querySelectorAll('.tc-stat-number');
		if (!els.length) return;

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

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

	/* -------------------------------------------------------------------------
	   Ripple — fires on mousedown/touchstart, sustains while held
	   Auto-applied to .wp-block-button__link and any .tc-ripple element.
	   CSS handles the wave animation; JS only creates/removes the span.
	------------------------------------------------------------------------- */
	var RIPPLE_DURATION = 550; // ms — matches CSS animation duration

	function spawnRipple(el, clientX, clientY) {
		var rect   = el.getBoundingClientRect();
		var x      = clientX - rect.left;
		var y      = clientY - rect.top;
		var size   = Math.max(rect.width, rect.height) * 2.5;

		var wave = document.createElement('span');
		wave.className = 'tc-ripple-wave';
		wave.style.cssText = [
			'width:'  + size + 'px',
			'height:' + size + 'px',
			'left:'   + (x - size / 2) + 'px',
			'top:'    + (y - size / 2) + 'px'
		].join(';');

		el.appendChild(wave);

		// Remove after animation completes (keeps DOM clean)
		setTimeout(function () { wave.remove(); }, RIPPLE_DURATION + 100);
	}

	function onRippleDown(e) {
		var el = e.currentTarget;
		var cx = e.clientX !== undefined ? e.clientX : e.touches[0].clientX;
		var cy = e.clientY !== undefined ? e.clientY : e.touches[0].clientY;
		spawnRipple(el, cx, cy);
		el.classList.add('tc-held');
	}

	function onRippleUp(e) {
		e.currentTarget.classList.remove('tc-held');
	}

	function initRipple() {
		var els = document.querySelectorAll('.wp-block-button__link, .tc-ripple');
		els.forEach(function (el) {
			el.addEventListener('mousedown',  onRippleDown);
			el.addEventListener('touchstart', onRippleDown, { passive: true });
			el.addEventListener('mouseup',    onRippleUp);
			el.addEventListener('mouseleave', onRippleUp);
			el.addEventListener('touchend',   onRippleUp);
		});
	}

	/* -------------------------------------------------------------------------
	   Menu filter — category tab nav for .tc-menu-section patterns
	   Reads data-category from .tc-menu-item children, builds tab buttons,
	   and filters items on click. Tabs injected before .tc-menu-grid.
	------------------------------------------------------------------------- */
	function initMenuFilter() {
		var sections = document.querySelectorAll('.tc-menu-section');
		if (!sections.length) return;

		sections.forEach(function (section) {
			var items = section.querySelectorAll('.tc-menu-item[data-category]');
			if (!items.length) return;

			// Collect unique categories preserving insertion order.
			var categories = [];
			items.forEach(function (item) {
				var cat = item.getAttribute('data-category');
				if (cat && categories.indexOf(cat) === -1) {
					categories.push(cat);
				}
			});

			// Only build tabs when there are multiple categories.
			if (categories.length < 2) return;

			var tabsEl = document.createElement('div');
			tabsEl.className = 'tc-menu-tabs';

			// "All" tab — shows every item.
			var allTab = buildTab('All', '', true);
			tabsEl.appendChild(allTab);

			categories.forEach(function (cat) {
				tabsEl.appendChild(buildTab(cat, cat, false));
			});

			// Insert tabs before the grid.
			var grid = section.querySelector('.tc-menu-grid');
			if (grid) {
				section.insertBefore(tabsEl, grid);
			}

			// Filter on tab click.
			tabsEl.addEventListener('click', function (e) {
				var btn = e.target.closest('.tc-menu-tab');
				if (!btn) return;

				tabsEl.querySelectorAll('.tc-menu-tab').forEach(function (t) {
					t.classList.remove('is-active');
				});
				btn.classList.add('is-active');

				var filter = btn.getAttribute('data-filter');
				items.forEach(function (item) {
					var match = !filter || item.getAttribute('data-category') === filter;
					item.style.display = match ? '' : 'none';
				});
			});
		});
	}

	function buildTab(label, filter, active) {
		var btn = document.createElement('button');
		btn.className = 'tc-menu-tab' + (active ? ' is-active' : '');
		btn.textContent = label;
		btn.setAttribute('data-filter', filter);
		btn.setAttribute('type', 'button');
		return btn;
	}

	/* -------------------------------------------------------------------------
	   Image slider — prev/next arrows, dot indicators, touch swipe, keyboard
	   Markup: .tc-slider > .tc-slider-track > .tc-slide[]
	           + .tc-slider-prev / .tc-slider-next buttons
	           + .tc-slider-dots (dots injected here by JS)
	------------------------------------------------------------------------- */
	function initSlider() {
		var sliders = document.querySelectorAll('.tc-slider');
		if (!sliders.length) return;

		sliders.forEach(function (slider) {
			var track  = slider.querySelector('.tc-slider-track');
			var slides = slider.querySelectorAll('.tc-slide');
			var prev   = slider.querySelector('.tc-slider-prev');
			var next   = slider.querySelector('.tc-slider-next');
			var dotsEl = slider.querySelector('.tc-slider-dots');

			if (!track || !slides.length) return;

			var total   = slides.length;
			var current = 0;

			if (total === 1) {
				slider.setAttribute('data-single', '');
				return;
			}

			// Build dot buttons
			if (dotsEl) {
				for (var d = 0; d < total; d++) {
					(function (index) {
						var dot = document.createElement('button');
						dot.className = 'tc-slider-dot' + (index === 0 ? ' is-active' : '');
						dot.setAttribute('aria-label', 'Slide ' + (index + 1));
						dot.setAttribute('type', 'button');
						dot.setAttribute('role', 'tab');
						dot.addEventListener('click', function () { goTo(index); });
						dotsEl.appendChild(dot);
					}(d));
				}
			}

			function goTo(index) {
				current = ((index % total) + total) % total;
				track.style.transform = 'translateX(-' + (current * 100) + '%)';
				if (dotsEl) {
					dotsEl.querySelectorAll('.tc-slider-dot').forEach(function (dot, i) {
						dot.classList.toggle('is-active', i === current);
					});
				}
			}

			if (prev) prev.addEventListener('click', function () { goTo(current - 1); });
			if (next) next.addEventListener('click', function () { goTo(current + 1); });

			// Keyboard nav when slider is focused
			slider.setAttribute('tabindex', '0');
			slider.addEventListener('keydown', function (e) {
				if (e.key === 'ArrowLeft')  { goTo(current - 1); e.preventDefault(); }
				if (e.key === 'ArrowRight') { goTo(current + 1); e.preventDefault(); }
			});

			// Touch swipe
			var touchX = 0;
			slider.addEventListener('touchstart', function (e) {
				touchX = e.touches[0].clientX;
			}, { passive: true });
			slider.addEventListener('touchend', function (e) {
				var diff = touchX - e.changedTouches[0].clientX;
				if (Math.abs(diff) > 40) goTo(diff > 0 ? current + 1 : current - 1);
			}, { passive: true });
		});
	}

	/* -------------------------------------------------------------------------
	   Testimonials marquee — clone items for seamless infinite scroll
	------------------------------------------------------------------------- */
	function initMarquee() {
		document.querySelectorAll('.tc-marquee-inner').forEach(function (inner) {
			var children = Array.from(inner.children);
			if (children.length === 0) return;
			children.forEach(function (child) {
				inner.appendChild(child.cloneNode(true));
			});
		});
	}

	/* -------------------------------------------------------------------------
	   Feather icons — initialise if the library is present on the page
	   (enqueued separately via wp_enqueue_script)
	------------------------------------------------------------------------- */
	function initFeather() {
		if (window.feather && typeof window.feather.replace === 'function') {
			window.feather.replace({ 'stroke-width': 1.5, width: 20, height: 20 });
		}
	}

	/* -------------------------------------------------------------------------
	   Pricing toggle — monthly / annual switch for .tc-pricing-toggle-section
	   Toggles aria-checked on the switch button and adds/removes .tc-pt-annual
	   class on each .tc-pt-cards container so CSS shows the right price.
	------------------------------------------------------------------------- */
	function initPricingToggle() {
		var sections = document.querySelectorAll('.tc-pricing-toggle-section');
		if (!sections.length) return;

		sections.forEach(function (section) {
			var btn = section.querySelector('.tc-pt-switch');
			if (!btn) return;
			var cards = section.querySelector('.tc-pt-cards');

			btn.addEventListener('click', function () {
				var isAnnual = btn.getAttribute('aria-checked') === 'true';
				btn.setAttribute('aria-checked', isAnnual ? 'false' : 'true');
				if (cards) {
					cards.classList.toggle('tc-pt-annual', !isAnnual);
				}
			});
		});
	}

	/* -------------------------------------------------------------------------
	   Boot
	------------------------------------------------------------------------- */
	function boot() {
		initFade();
		initStagger();
		initCounters();
		initRipple();
		initSlider();
		initMenuFilter();
		initMarquee();
		initPricingToggle();
		initFeather();
	}

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

	/* Public API (for debugging / manual trigger) */
	TC.refresh = boot;

}());
