/**
 * Admin JS for Custom Animated Preloader
 */
jQuery(document).ready(function ($) {

	// Tab Switching (Now handled via PHP and submenus)
	/*
	$('.swap-nav-item').on('click', function (e) {
		e.preventDefault();
		var target = $(this).attr('href');

		// Remove active class from all tabs and content
		$('.swap-nav-item').removeClass('active');
		$('.swap-tab-content').removeClass('active');

		// Add active class to clicked tab and target content
		$(this).addClass('active');
		$(target).addClass('active');
	});
	*/

	// Range Slider Value Update
	$('input[type="range"][name="swap_settings[bg_opacity]"]').on('input', function () {
		$(this).next('.swap-range-value').text($(this).val() + '%');
	});

	// Spinner Selection Highlight
	// Update selected state when clicking the card (triggered by label click usually)
	$('.swap-card input[type="radio"]').on('change', function () {
		$('.swap-grid .swap-card').removeClass('selected');
		if ($(this).is(':checked')) {
			$(this).closest('.swap-card').addClass('selected');
		}
	});

	// Initial check for selected spinner (in case of browser refresh keeping state)
	$('.swap-card input[type="radio"]:checked').closest('.swap-card').addClass('selected');

	// Device Card Toggle
	$('.swap-device-card').on('click', function () {
		var $card = $(this);
		var $input = $card.find('.swap-device-input');
		var isAllCard = ($input.val() === 'all');

		if (isAllCard) {
			// If "All Devices" is clicked, uncheck all specific device cards
			$('.swap-device-card').not($card).removeClass('active').find('.swap-device-input').prop('checked', false);
			$('.swap-device-card').not($card).find('.swap-device-status').text('Disabled');
			$card.addClass('active');
			$input.prop('checked', true);
			$card.find('.swap-device-status').text('Enabled');
		} else {
			// Toggle clicked card
			$card.toggleClass('active');
			var isNowChecked = $card.hasClass('active');
			$input.prop('checked', isNowChecked);
			$card.find('.swap-device-status').text(isNowChecked ? 'Enabled' : 'Disabled');

			// Uncheck "All Devices" if any specific device is toggled
			var $allCard = $('.swap-device-card').filter(function () {
				return $(this).find('.swap-device-input').val() === 'all';
			});
			$allCard.removeClass('active').find('.swap-device-input').prop('checked', false);
			$allCard.find('.swap-device-status').text('Disabled');
		}
	});

	// ============================================================
	// AJAX Page Search Logic
	// ============================================================
	var searchTimeout;
	var $searchInput = $('#swap-page-search');
	var $resultsList = $('#swap-search-results');
	var $tagsContainer = $('#swap-exclude-tags');
	var $idInput = $('#swap-excluded-ids');

	// 1. Handle Search Input (Debounced)
	$searchInput.on('input', function () {
		var term = $(this).val().trim();
		clearTimeout(searchTimeout);

		if (term.length < 2) {
			$resultsList.hide().empty();
			return;
		}

		searchTimeout = setTimeout(function () {
			$.ajax({
				url: swap_vars.ajaxurl,
				type: 'GET',
				data: {
					action: 'swap_search_pages',
					term: term,
					nonce: swap_vars.nonce
				},
				success: function (response) {
					if (response.success) {
						renderResults(response.data);
					} else {
						console.log('Search error:', response);
					}
				}
			});
		}, 300);
	});

	// 2. Render Search Results
	function renderResults(results) {
		$resultsList.empty();
		if (results.length === 0) {
			$resultsList.append('<li class="swap-no-results">No pages found</li>');
		} else {
			results.forEach(function (item) {
				$resultsList.append(
					'<li class="swap-search-result-item" data-id="' + item.id + '" data-text="' + item.text + '">' +
					item.text +
					'</li>'
				);
			});
		}
		$resultsList.show();
	}

	// 3. Select Result -> Add ID and Tag
	$(document).on('click', '.swap-search-result-item', function () {
		var id = $(this).data('id');
		var text = $(this).data('text'); // e.g. "Sample Page (ID: 10)"
		// Clean text for pill (remove ID part for shorter look? optional)
		var pillText = text.replace(/\(ID: \d+\)/, '').trim();

		addId(id);
		addTag(id, pillText);

		$searchInput.val('');
		$resultsList.hide().empty();
	});

	// 4. Dismiss Tag -> Remove ID
	$(document).on('click', '.swap-pill .dashicons', function () {
		var $tag = $(this).closest('.swap-pill');
		var id = $tag.data('id');

		removeId(id);
		$tag.fadeOut(200, function () {
			$(this).remove();
		});
	});

	// Helper: Add ID to comma-separated input
	function addId(id) {
		var current = $idInput.val().split(',').map(s => s.trim()).filter(Boolean);
		if (!current.includes(id.toString())) {
			current.push(id);
			$idInput.val(current.join(', '));
		}
	}

	// Helper: Remove ID from input
	function removeId(id) {
		var current = $idInput.val().split(',').map(s => s.trim()).filter(Boolean);
		var index = current.indexOf(id.toString());
		if (index > -1) {
			current.splice(index, 1);
			$idInput.val(current.join(', '));
		}
	}

	// Helper: Append Tag Visual
	function addTag(id, text) {
		// Check if tag already exists to confirm visual sync
		if ($tagsContainer.find('.swap-pill[data-id="' + id + '"]').length === 0) {
			$tagsContainer.append(
				'<span class="swap-pill" data-id="' + id + '">' + text + ' <span class="dashicons dashicons-no-alt"></span></span>'
			);
		}
	}

	// ============================================================
	// Custom Dropdown (Script Loading)
	// ============================================================
	var $dropdown = $('#swap-script-loading-dropdown');
	var $dropdownTrigger = $dropdown.find('.swap-dropdown-trigger');
	var $dropdownOptions = $dropdown.find('.swap-dropdown-options');
	var $hiddenInput = $('#swap_script_loading');
	var $dropdownText = $dropdown.find('.swap-dropdown-text');

	// Toggle Dropdown
	$dropdownTrigger.on('click', function (e) {
		e.stopPropagation();
		$dropdown.toggleClass('active');
	});

	// Select Option
	$dropdownOptions.on('click', 'li', function (e) {
		e.stopPropagation();
		var value = $(this).data('value');
		var text = $(this).find('span').first().text();

		// Update Input
		$hiddenInput.val(value);

		// Update Trigger Text (optional: keep full text or truncate?)
		$dropdownText.text(text);

		// Visual Selection Update
		$dropdownOptions.find('li').removeClass('selected');
		$dropdownOptions.find('.dashicons-yes').remove();

		$(this).addClass('selected');
		$(this).append('<span class="dashicons dashicons-yes"></span>');

		// Close
		$dropdown.removeClass('active');
	});

	// Close on Outside Click
	$(document).on('click', function (e) {
		if ($dropdown.length && !$dropdown.is(e.target) && $dropdown.has(e.target).length === 0) {
			$dropdown.removeClass('active');
		}

		if (!$(e.target).closest('.swap-exclude-search-wrap').length) {
			$resultsList.hide();
		}
	});



	// ============================================================
	// Text & Logo Tab Logic
	// ============================================================

	// Logo Size Slider Sync
	$('#swap-logo-size-range').on('input', function () {
		$('#swap-logo-size-val').text($(this).val() + 'px');
		$('#swap-tl-preview-logo').css('max-width', $(this).val() + 'px');
	});

	// Readymade Size Slider Sync
	$('#swap-style-size-range').on('input', function () {
		var size = $(this).val();
		$('#swap-style-size-val').text(size + 'px');
	});

	// Font Size Slider Sync
	$('#swap-font-size-range').on('input', function () {
		var size = $(this).val();
		$('#swap-font-size-val').text(size + 'px');
		$('#swap-tl-preview-text').css('font-size', size + 'px');
	});

	// Loading Text Live Preview (Toggle visibility based on content)
	$('input[name="swap_settings[loading_text]"]').on('input', function () {
		var text = $(this).val();
		var $preview = $('#swap-tl-preview-text');
		$preview.text(text);
		if (text.trim() === '') {
			$preview.hide();
		} else {
			$preview.show();
		}
	});

	// Text Color Live Preview
	$('input[name="swap_settings[text_color]"]').on('input', function () {
		var val = $(this).val();
		$('#swap-tl-preview-text').css({
			'color': val,
			'--loader-color': val
		});
		$(this).closest('.swap-color-picker-wrap').find('.swap-hex-input').val(val);
	});

	// Font Weight Live Preview
	$('select[name="swap_settings[font_weight]"]').on('change', function () {
		$('#swap-tl-preview-text').css('font-weight', $(this).val());
	});

	// Logo Upload via WP Media Library
	$('.swap-logo-upload-area').on('click', function (e) {
		// If clicking remove button, don't trigger upload
		if ($(e.target).closest('#swap-logo-remove-btn').length) return;

		e.preventDefault();
		var frame = wp.media({
			title: 'Select Logo',
			button: { text: 'Use This Logo' },
			multiple: false,
			library: { type: 'image' }
		});
		frame.on('select', function () {
			var attachment = frame.state().get('selection').first().toJSON();
			$('#swap-logo-url').val(attachment.url);

			// Update the upload area preview
			$('#swap-logo-preview').css({
				'display': 'flex',
				'background-image': 'url(' + attachment.url + ')',
				'background-size': 'contain',
				'background-repeat': 'no-repeat'
			});

			// Update live preview frame
			var $previewWrap = $('#swap-tl-preview-frame-logo .swap-preview-loader-wrap');
			$previewWrap.find('#swap-tl-preview-spinner').remove();
			if ($previewWrap.find('#swap-tl-preview-logo').length) {
				$previewWrap.find('#swap-tl-preview-logo').attr('src', attachment.url);
			} else {
				var logoSize = $('#swap-logo-size-range').val() || 180;
				$previewWrap.prepend('<img src="' + attachment.url + '" id="swap-tl-preview-logo" style="max-width:' + logoSize + 'px; height:auto;" alt="Logo Preview">');
			}
		});
		frame.open();
	});

	// Remove Logo Handler
	$('#swap-logo-remove-btn').on('click', function (e) {
		e.stopPropagation();
		$('#swap-logo-url').val('');
		$('#swap-logo-preview').hide().css('background-image', '');

		// Update Preview
		var $previewWrap = $('#swap-tl-preview-frame-logo .swap-preview-loader-wrap');
		$previewWrap.find('#swap-tl-preview-logo').remove();

		// If it's the logo preloader tab, we might want to put back a placeholder or spinner in preview?
		// For now, removing is fine as per current logic.
	});

	// Normal Text Toggle Logic
	$('#swap-use-normal-toggle').on('change', function () {
		var isChecked = $(this).is(':checked');
		if (isChecked) {
			$('#swap-use-readymade-toggle').prop('checked', false);
			$('#swap-readymade-grid-wrap').hide();
		}
		$('#swap-normal-text-settings').toggle(isChecked);
		updateLivePreview();
	});

	// Readymade Styles Toggle Logic
	$('#swap-use-readymade-toggle').on('change', function () {
		var isChecked = $(this).is(':checked');
		if (isChecked) {
			$('#swap-use-normal-toggle').prop('checked', false);
			$('#swap-normal-text-settings').hide();
		}
		$('#swap-readymade-grid-wrap').toggle(isChecked);
		updateLivePreview();
	});

	// Readymade Style Item Click
	$('.swap-readymade-item').on('click', function () {
		var styleId = $(this).data('style');
		$('#swap-readymade-style-hidden').val(styleId);
		$('.swap-readymade-item').removeClass('active');
		$(this).addClass('active');

		// Auto-enable readymade switch if not already ON
		var $rmToggle = $('#swap-use-readymade-toggle');
		var $normToggle = $('#swap-use-normal-toggle');
		if (!$rmToggle.prop('checked')) {
			$rmToggle.prop('checked', true).trigger('change');
		}

		updateLivePreview();
	});

	// Helper to update live preview
	function updateLivePreview() {
		var isNormal = $('#swap-use-normal-toggle').is(':checked');
		var isReadymade = $('#swap-use-readymade-toggle').is(':checked');
		var $previewText = $('#swap-tl-preview-text');
		var loadingText = $('input[name="swap_settings[loading_text]"]').val();

		// Reset classes
		$previewText.removeClass(function (index, className) {
			return (className.match(/(^|\s)swap-text-loader-\S+/g) || []).join(' ');
		});
		$previewText.removeClass(function (index, className) {
			return (className.match(/(^|\s)swap-anim-\S+/g) || []).join(' ');
		});

		$previewText.text(loadingText);

		if (isReadymade) {
			var styleId = $('#swap-readymade-style-hidden').val();
			$previewText.addClass('swap-text-loader-' + styleId);
		} else if (isNormal) {
			var anim = $('input[name="swap_settings[text_animation]"]').val();
			if (anim && anim !== 'none') {
				$previewText.addClass('swap-anim-' + anim);
			}
		}

		// Apply size and color (shared)
		var fontSize = $('#swap-font-size-range').val();
		var textColor = $('input[name="swap_settings[text_color]"]').val();
		var fontFamily = $('.swap-font-dropdown input[type="hidden"]').val();

		$previewText.css({
			'font-size': fontSize + 'px',
			'color': textColor,
			'--loader-color': textColor,
			'font-family': fontFamily ? fontFamily + ', sans-serif' : ''
		});
	}

	// Connect existing controls to the new preview logic
	$('#swap-font-size-range, input[name="swap_settings[text_color]"], input[name="swap_settings[loading_text]"]').on('input change', function () {
		var val = $('input[name="swap_settings[loading_text]"]').val();
		$('.swap-readymade-preview div[class^="swap-text-loader-"]').text(val).attr('data-text', val);
		updateLivePreview();
	});

	$('.swap-font-dropdown input[type="hidden"], .swap-custom-dropdown[data-target="swap_settings[text_animation]"] input[type="hidden"]').on('change', function () {
		updateLivePreview();
	});


	// ============================================================
	// Custom Dropdown Component
	// ============================================================

	// Toggle dropdown open/close
	$(document).on('click', '.swap-dd-trigger', function (e) {
		e.stopPropagation();
		var $dd = $(this).closest('.swap-custom-dropdown');
		// Close all other dropdowns first
		$('.swap-custom-dropdown').not($dd).removeClass('active');
		$dd.toggleClass('active');
	});

	// Select an option
	$(document).on('click', '.swap-dd-options li:not(.swap-dd-divider):not(.swap-dd-upload-font)', function () {
		var $dd = $(this).closest('.swap-custom-dropdown');
		var val = $(this).data('value');
		var text = $(this).clone().children().remove().end().text().trim();

		// Update hidden input
		$dd.find('input[type="hidden"]').val(val).trigger('change');

		// Update trigger text
		$dd.find('.swap-dd-text').text(text);

		// Update visual selection
		$dd.find('.swap-dd-options li').removeClass('selected');
		$dd.find('.swap-dd-options li .dashicons-yes').remove();
		$(this).addClass('selected');
		$(this).append('<span class="dashicons dashicons-yes"></span>');

		// Font family preview: update trigger font-family
		if ($dd.hasClass('swap-font-dropdown')) {
			var font = $(this).data('font') || '';
			$dd.find('.swap-dd-text').css('font-family', font ? font + ', sans-serif' : '');
			// Update live preview
			$('#swap-tl-preview-text').css('font-family', font ? font + ', sans-serif' : '');
			// Hide custom font upload if a preset is selected
			$('#swap-custom-font-area').hide();
		}

		// Live preview: font weight
		var target = $dd.data('target');
		if (target === 'swap_settings[font_weight]') {
			$('#swap-tl-preview-text').css('font-weight', val);
		}

		// Close
		$dd.removeClass('active');
	});

	// Upload Custom Font option
	$(document).on('click', '.swap-dd-upload-font', function () {
		var $dd = $(this).closest('.swap-custom-dropdown');
		$dd.removeClass('active');
		$('#swap-custom-font-area').show();
	});

	// Custom Font File Upload
	$('#swap-upload-font-btn').on('click', function (e) {
		e.preventDefault();
		var frame = wp.media({
			title: 'Select Font File',
			button: { text: 'Use This Font' },
			multiple: false
		});
		frame.on('select', function () {
			var attachment = frame.state().get('selection').first().toJSON();
			$('#swap-custom-font-url').val(attachment.url);
			$('#swap-font-filename').text(attachment.filename || attachment.url.split('/').pop());
			// Set font_family to filename without extension
			var fontName = (attachment.filename || attachment.url.split('/').pop()).replace(/\.[^.]+$/, '');
			var $fontDd = $('.swap-font-dropdown');
			$fontDd.find('input[type="hidden"]').val(fontName);
			$fontDd.find('.swap-dd-text').text(fontName);
			$fontDd.find('.swap-dd-options li').removeClass('selected');
			$fontDd.find('.swap-dd-options li .dashicons-yes').remove();
		});
		frame.open();
	});

	// Close dropdowns on outside click
	$(document).on('click', function () {
		$('.swap-custom-dropdown').removeClass('active');
	});

	// ============================================================
	// Progress & Timing Tab – Live Preview
	// ============================================================

	// Show Percentage Toggle
	$('input[name="swap_settings[show_percentage]"]').on('change', function () {
		$('#swap-pt-preview-percentage').toggle(this.checked);
	});

	// Show Progress Bar Toggle
	$('input[name="swap_settings[show_progress_bar]"]').on('change', function () {
		$('#swap-pt-preview-bar').toggle(this.checked);
	});

	// Progress Bar Color Sync
	$('input[name="swap_settings[progress_bar_color]"]').on('input', function () {
		$('.swap-pt-bar-fill').css('background', $(this).val());
		$(this).closest('.swap-color-picker-wrap').find('.swap-hex-input').val($(this).val());
	});

	// ============================================================
	// Style Tab – Template Card Selection
	// ============================================================
	// ============================================================
	// Inline Loader Color Picker Popover
	// ============================================================

	// ============================================================
	// Inline Expandable Color Picker (Presets + Custom View)
	// ============================================================

	// State for Dragging
	var activeDrag = {
		type: null, // 'sat' or 'hue'
		$el: null,  // The saturation or hue element being dragged
		state: { h: 0, s: 0, v: 100 } // Local state for the active picker
	};
	var $activeCard = null; // Track which card is being edited

	// --- Math Helpers ---
	function hsvToRgb(h, s, v) {
		h /= 360; s /= 100; v /= 100;
		var r, g, b, i, f, p, q, t;

		if (s === 0) { // Achromatic (grey)
			r = g = b = v;
			return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
		}

		i = Math.floor(h * 6);
		f = h * 6 - i;
		p = v * (1 - s);
		q = v * (1 - f * s);
		t = v * (1 - (1 - f) * s);
		switch (i % 6) {
			case 0: r = v; g = t; b = p; break;
			case 1: r = q; g = v; b = p; break;
			case 2: r = p; g = v; b = t; break;
			case 3: r = p; g = q; b = v; break;
			case 4: r = t; g = p; b = v; break;
			case 5: r = v; g = p; b = q; break;
		}
		return { r: Math.round(r * 255), g: Math.round(g * 255), b: Math.round(b * 255) };
	}

	function rgbToHex(r, g, b) {
		return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
	}

	function hexToRgb(hex) {
		var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
		return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : null;
	}

	function rgbToHsv(r, g, b) {
		r /= 255; g /= 255; b /= 255;
		var max = Math.max(r, g, b), min = Math.min(r, g, b);
		var h, s, v = max;
		var d = max - min;
		s = max === 0 ? 0 : d / max;
		if (max === min) h = 0;
		else {
			switch (max) {
				case r: h = (g - b) / d + (g < b ? 6 : 0); break;
				case g: h = (b - r) / d + 2; break;
				case b: h = (r - g) / d + 4; break;
			}
			h /= 6;
		}
		if (h < 0) h += 1;
		return { h: h * 360, s: s * 100, v: v * 100 };
	}

	// --- Picker Update Logic ---
	function updatePickerUI($popover, h, s, v) {
		var $satBox = $popover.find('.swap-cp-saturation');
		var $satCursor = $popover.find('.swap-cp-cursor');
		var $hueCursor = $popover.find('.swap-cp-hue-cursor');
		var $preview = $popover.find('.swap-cp-preview');
		var $hexInput = $popover.find('.swap-cp-hex');

		// 1. Saturation BG
		var hueRGB = hsvToRgb(h, 100, 100);
		$satBox.css('background', 'rgb(' + hueRGB.r + ',' + hueRGB.g + ',' + hueRGB.b + ')');

		// 2. Cursors
		$satCursor.css({ left: s + '%', top: (100 - v) + '%' });
		$hueCursor.css('left', (h / 360 * 100) + '%');
		$hueCursor.css('background', 'rgb(' + hueRGB.r + ',' + hueRGB.g + ',' + hueRGB.b + ')');

		// 3. Result
		var finalRGB = hsvToRgb(h, s, v);
		var hex = rgbToHex(finalRGB.r, finalRGB.g, finalRGB.b);

		$preview.css('background', hex);
		if (!$hexInput.is(':focus')) $hexInput.val(hex);

		// 4. Update Card & Hidden Input
		if ($activeCard) {
			$activeCard.find('.swap-tmpl-preview').css('--swap-loader-color', hex);
			// Update hidden input if this is the active card
			if ($activeCard.hasClass('swap-tmpl-selected')) {
				$('#swap-lc-hex').val(hex);
			}
		}
	}

	function setPickerColor($popover, hex) {
		var rgb = hexToRgb(hex);
		if (rgb) {
			var hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
			// Store state in DOM data for this instance? Or just use local var if active?
			// Since drag uses `activeDrag.state`, we update that if dragging.
			// But for initialization, we just update UI.
			updatePickerUI($popover, hsv.h, hsv.s, hsv.v);
			return hsv;
		}
		return { h: 0, s: 0, v: 100 };
	}

	// --- Event Handlers ---

	// 1. Select Card & Show Inline Popover
	$('.swap-tmpl-card:not(.swap-tmpl-locked)').on('click', function (e) {
		// Ignore clicks on controls
		if ($(e.target).closest('.swap-lc-popover, .swap-tmpl-edit-icon').length) return;

		var $card = $(this);
		$activeCard = $card;
		var $popover = $('#swap-lc-popover'); // The single global instance

		// Clean others
		$('.swap-tmpl-card').removeClass('swap-tmpl-selected');
		$('.swap-tmpl-check').remove();
		$popover.hide();

		$card.addClass('swap-tmpl-selected');
		$card.find('input[type="radio"]').prop('checked', true);

		// If this template is flagged as no-color (hardcoded palette), abort showing picker
		if ($card.find('.no-color').length > 0) {
			$popover.hide();
			// Ensure it still clearly shows it was selected
			$card.find('.swap-tmpl-preview').append('<div class="swap-tmpl-check"><span class="dashicons dashicons-yes-alt"></span> Selected</div>');
			return;
		}

		// MOVE popover to this card
		$card.find('.swap-tmpl-preview').append($popover);

		// Reset View & Show
		$popover.find('.swap-lc-view-presets').show();
		$popover.find('.swap-lc-view-custom').hide();
		$popover.fadeIn(200);

		// Sync Global Input
		var currentHex = $card.find('.swap-tmpl-preview').css('--swap-loader-color') || '#ffffff';
		if (currentHex.indexOf('rgb') > -1) {
			// Basic rgb check, relying on setPickerColor to parse
		}
		$('#swap-lc-hex').val(currentHex);

		// Init picker
		let initHex = currentHex;
		if (initHex.indexOf('rgb') > -1) {
			let rgb = initHex.match(/\d+/g);
			if (rgb) initHex = rgbToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
		}
		setPickerColor($popover, initHex && initHex.indexOf('#') === 0 ? initHex : '#ffffff');
	});

	// 2. Preset Click (Delegated)
	$(document).on('click', '.swap-lc-preset', function (e) {
		e.stopPropagation();
		var hex = $(this).data('color');
		if ($activeCard) {
			$activeCard.find('.swap-tmpl-preview').css('--swap-loader-color', hex);
			$('#swap-lc-hex').val(hex);
			// Update active preset styling
			$activeCard.find('.swap-lc-preset').removeClass('swap-lc-active');
			$(this).addClass('swap-lc-active');
		}
	});

	// 3. Toggle Custom View (Delegated)
	$(document).on('click', '.swap-lc-custom-trigger', function (e) {
		e.stopPropagation();
		var $popover = $(this).closest('.swap-lc-popover');

		// Initialize Picker with current color
		var currentHex = $activeCard.find('.swap-tmpl-preview').css('--swap-loader-color');
		// Convert rgb to hex for init
		if (currentHex && currentHex.indexOf('rgb') > -1) {
			var rgb = currentHex.match(/\d+/g);
			if (rgb) currentHex = rgbToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
		}
		if (!currentHex || currentHex.indexOf('#') !== 0) currentHex = '#ffffff';

		setPickerColor($popover, currentHex);

		// Switch Views
		$popover.find('.swap-lc-view-presets').hide();
		$popover.find('.swap-lc-view-custom').fadeIn(200);
	});

	// 4. Back Button (Delegated)
	$(document).on('click', '.swap-lc-back', function (e) {
		e.stopPropagation();
		var $popover = $(this).closest('.swap-lc-popover');
		$popover.find('.swap-lc-view-custom').hide();
		$popover.find('.swap-lc-view-presets').fadeIn(200);
	});

	// 5. Done / Select Button (Delegated)
	$(document).on('click', '.swap-lc-done, .swap-lc-select-custom', function (e) {
		e.stopPropagation();
		var $popover = $(this).closest('.swap-lc-popover');
		$popover.fadeOut(200, function () {
			if ($activeCard) {
				if ($activeCard.find('.swap-tmpl-check').length === 0) {
					if ($activeCard.find('.no-color').length > 0) {
						$activeCard.find('.swap-tmpl-preview').append(
							'<div class="swap-tmpl-check"><span class="dashicons dashicons-yes-alt"></span> Selected</div>'
						);
					} else {
						$activeCard.find('.swap-tmpl-preview').append(
							'<div class="swap-tmpl-check"><span class="dashicons dashicons-yes-alt"></span> Selected <span class="dashicons dashicons-edit swap-tmpl-edit-icon" title="Edit Color"></span></div>'
						);
					}
				}
			}
		});
	});

	// 6. Edit Icon
	$(document).on('click', '.swap-tmpl-edit-icon', function (e) {
		e.stopPropagation();
		var $card = $(this).closest('.swap-tmpl-card');
		$activeCard = $card;
		$(this).closest('.swap-tmpl-check').remove();

		var $popover = $('#swap-lc-popover');
		$card.find('.swap-tmpl-preview').append($popover);

		$popover.find('.swap-lc-view-presets').show();
		$popover.find('.swap-lc-view-custom').hide();
		$popover.fadeIn(200);

		// Init color
		var currentHex = $card.find('.swap-tmpl-preview').css('--swap-loader-color');
		if (currentHex && currentHex.indexOf('rgb') > -1) {
			var rgb = currentHex.match(/\d+/g);
			if (rgb) currentHex = rgbToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
		}
		setPickerColor($popover, currentHex || '#ffffff');
	});

	// --- Drag Logic (Scoped) ---

	function handleDrag(e) {
		if (!activeDrag.$el) return;

		var $el = activeDrag.$el;
		var offset = $el.offset();
		var width = $el.width();
		var height = $el.height();
		var x = e.pageX - offset.left;

		// Clamp
		x = Math.max(0, Math.min(x, width));

		if (activeDrag.type === 'sat') {
			var y = e.pageY - offset.top;
			y = Math.max(0, Math.min(y, height));

			activeDrag.state.s = (x / width) * 100;
			activeDrag.state.v = 100 - (y / height) * 100;
		} else if (activeDrag.type === 'hue') {
			activeDrag.state.h = (x / width) * 360;
		}

		// Update UI of the PARENT popover
		var $popover = $el.closest('.swap-lc-popover');
		updatePickerUI($popover, activeDrag.state.h, activeDrag.state.s, activeDrag.state.v);
	}

	// Mousedown Handlers
	$('.swap-tmpl-card').on('mousedown', '.swap-cp-saturation', function (e) {
		// Identify current state
		var $popover = $(this).closest('.swap-lc-popover');
		// Re-derive state from current color or UI? 
		// For simplicity, we can fetch from computed style or stored data.
		// Let's re-parse current color to ensure sync
		var currentHex = $activeCard.find('.swap-tmpl-preview').css('--swap-loader-color');
		if (currentHex.indexOf('rgb') > -1) {
			var rgb = currentHex.match(/\d+/g);
			currentHex = rgbToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
		}
		var hsv = rgbToHsv(hexToRgb(currentHex).r, hexToRgb(currentHex).g, hexToRgb(currentHex).b);

		activeDrag = {
			type: 'sat',
			$el: $(this),
			state: hsv
		};
		handleDrag(e);
		e.preventDefault();
	});

	$('.swap-tmpl-card').on('mousedown', '.swap-cp-hue', function (e) {
		var $popover = $(this).closest('.swap-lc-popover');
		// Re-derive state
		var currentHex = $activeCard.find('.swap-tmpl-preview').css('--swap-loader-color');
		if (currentHex.indexOf('rgb') > -1) {
			var rgb = currentHex.match(/\d+/g);
			currentHex = rgbToHex(parseInt(rgb[0]), parseInt(rgb[1]), parseInt(rgb[2]));
		}
		var hsv = rgbToHsv(hexToRgb(currentHex).r, hexToRgb(currentHex).g, hexToRgb(currentHex).b);

		activeDrag = {
			type: 'hue',
			$el: $(this),
			state: hsv
		};
		handleDrag(e);
		e.preventDefault();
	});

	// Global Mouse Events
	$(window).on('mousemove', function (e) {
		if (activeDrag.$el) {
			handleDrag(e);
			e.preventDefault();
		}
	}).on('mouseup', function () {
		activeDrag.$el = null;
	});

	// Hex Input Manual Entry
	$('.swap-tmpl-card').on('input', '.swap-cp-hex', function () {
		var val = $(this).val();
		if (/^#[0-9a-fA-F]{6}$/.test(val)) {
			var $popover = $(this).closest('.swap-lc-popover');
			setPickerColor($popover, val);
		}
	});

	// Eyedropper
	if (window.EyeDropper) {
		$('.swap-tmpl-card').on('click', '#swap-cp-eyedropper', function () {
			var $popover = $(this).closest('.swap-lc-popover');
			new EyeDropper().open().then(function (res) {
				setPickerColor($popover, res.sRGBHex);
			});
		});
	} else {
		$('#swap-cp-eyedropper').hide();
	}

	// Prevent closing when clicking inside
	// $('.swap-lc-popover').on('click', function (e) { e.stopPropagation(); });

	// On Load Initialization
	(function () {
		var serverVal = $('#swap-lc-hex').val() || '#ffffff';
		var $selected = $('.swap-tmpl-card input:checked').closest('.swap-tmpl-card');
		if ($selected.length) {
			$activeCard = $selected;
			$selected.addClass('swap-tmpl-selected');
			$selected.find('.swap-tmpl-preview').css('--swap-loader-color', serverVal);
			if ($selected.find('.swap-tmpl-check').length === 0) {
				if ($selected.find('.no-color').length > 0) {
					$selected.find('.swap-tmpl-preview').append(
						'<div class="swap-tmpl-check"><span class="dashicons dashicons-yes-alt"></span> Selected</div>'
					);
				} else {
					$selected.find('.swap-tmpl-preview').append(
						'<div class="swap-tmpl-check"><span class="dashicons dashicons-yes-alt"></span> Selected <span class="dashicons dashicons-edit swap-tmpl-edit-icon"></span></div>'
					);
				}
			}
		}

		// Initialize Text Preview
		if (typeof updateLivePreview === 'function') {
			updateLivePreview();
		}
	})();

	// 4. Edit Icon Click -> Show Popover Again

	// =========================================================
	// AJAX Save (No Page Reload)
	// =========================================================
	(function () {
		var $form = $('form.swap-main');
		// Target all status badges by class so it works on any tab
		var $statusBadges = $('.swap-style-sidebar-status');

		// Intercept ALL form submits (both native submit button and sidebar save button)
		$form.on('submit', function (e) {
			e.preventDefault();
			doAjaxSave($form);
		});

		// Also handle sidebar save button click
		$(document).on('click', '.swap-sidebar-save-btn', function (e) {
			e.preventDefault();
			doAjaxSave($form);
		});

		function doAjaxSave($form) {
			var $btn = $('.swap-sidebar-save-btn');
			var origText = $btn.html();

			// Show loading state
			$btn.html('<span class="dashicons dashicons-update swap-spin"></span> Saving...').prop('disabled', true);

			$.ajax({
				url: swap_vars.ajaxurl,
				type: 'POST',
				data: {
					action: 'swap_ajax_save',
					nonce: swap_vars.nonce,
					form_data: $form.serialize()
				},
				success: function (response) {
					// Restore button
					$btn.html(origText).prop('disabled', false);

					if (response.success) {
						// Show status badge
						$statusBadges.slideDown(200);
						setTimeout(function () {
							$statusBadges.slideUp(300);
						}, 3000);
					} else {
						alert('Save failed: ' + (response.data && response.data.message ? response.data.message : 'Unknown error'));
					}
				},
				error: function () {
					$btn.html(origText).prop('disabled', false);
					alert('Save failed. Please try again.');
				}
			});
		}
	})();

	// =========================================================
	// Preloader Type Toggle (Mutual Exclusion)
	// =========================================================
	(function () {
		var $hiddenInput = $('#swap-active-type');
		var typeLabels = {
			style: 'Style',
			logo: 'Logo',
			text: 'Custom Text',
			progress_timing: 'Progress and Percentage'
		};

		$(document).on('change', '.swap-type-toggle', function () {
			var $toggle = $(this);
			var type = $toggle.data('type');
			var isChecked = $toggle.is(':checked');
			var previousType = $hiddenInput.val();

			if (isChecked) {
				// Set hidden input to this type
				$hiddenInput.val(type);

				// Uncheck all OTHER toggles
				$('.swap-type-toggle').not($toggle).prop('checked', false);

				// Hide all info boxes first
				$('.swap-type-info-box').slideUp(200);

				// If a different type was previously active, show info box
				if (previousType !== 'none' && previousType !== type) {
					var prevLabel = typeLabels[previousType] || previousType;
					var newLabel = typeLabels[type] || type;
					var $infoBox = $toggle.closest('.swap-style-sidebar-card').find('.swap-type-info-box');
					$infoBox.find('.swap-type-info-text').text(
						'Switched to ' + newLabel + ' preloader. ' + prevLabel + ' preloader has been disabled.'
					);
					$infoBox.slideDown(200);
					setTimeout(function () {
						$infoBox.slideUp(300);
					}, 5000);
				}
			} else {
				// Turning OFF — set to none
				$hiddenInput.val('none');
				$('.swap-type-info-box').slideUp(200);
			}
		});
	})();

	// =========================================================
	// Range Slider Value Display
	// =========================================================
	$('.swap-range-slider').on('input', function () {
		var id = $(this).attr('id');
		// Map slider ID to its display span ID
		var displayMap = {
			'swap-font-size-range': 'swap-font-size-val',
			'swap-percentage-size-range': 'swap-percentage-size-val',
			'swap-bar-height-range': 'swap-bar-height-val'
		};
		var displayId = displayMap[id];
		if (displayId) {
			$('#' + displayId).text($(this).val());
		}
	});

	// =========================================================
	// Background Controls Sync Across Sidebars
	// =========================================================
	(function () {
		// Helper to update all live preview frames
		function updateBackgroundPreview() {
			var $anySidebar = $('.swap-bg-sync-block').first();
			var opacity = $anySidebar.find('.swap-bg-opacity-range').val() / 100;
			var type = $anySidebar.find('input[name="swap_settings[bg_type]"]:checked').val();
			var color = $anySidebar.find('.swap-bg-color-sync').val();
			var gradStart = $anySidebar.find('.swap-bg-grad-start-sync').val();
			var gradEnd = $anySidebar.find('.swap-bg-grad-end-sync').val();
			var gradAngle = $anySidebar.find('.swap-bg-angle-sync').val();
			var imageUrl = $anySidebar.find('.swap-bg-image-url-sync').val();
			var imageSize = $anySidebar.find('.swap-bg-image-size-sync').val();
			var imagePos = $anySidebar.find('.swap-bg-image-position-sync').val();

			var bgStyles = {};
			if (type === 'solid') {
				bgStyles['background'] = color;
			} else if (type === 'gradient') {
				bgStyles['background'] = 'linear-gradient(' + gradAngle + 'deg, ' + gradStart + ' 0%, ' + gradEnd + ' 100%)';
			} else if (type === 'image') {
				bgStyles['background-image'] = 'url(' + imageUrl + ')';
				bgStyles['background-size'] = imageSize;
				bgStyles['background-position'] = imagePos;
			}
			bgStyles['opacity'] = opacity;

			$('.swap-preview-bg-layer').css(bgStyles);
		}

		// Initial preview call
		updateBackgroundPreview();

		// Sync opacity range sliders
		$(document).on('input', '.swap-bg-opacity-range', function () {
			var val = $(this).val();
			$('.swap-bg-opacity-range').not(this).val(val);
			$('.swap-bg-opacity-text').val(val + '%');
			updateBackgroundPreview();
		});

		// Sync bg_type radio buttons and mode content visibility
		$(document).on('change', 'input[name="swap_settings[bg_type]"]', function () {
			var val = $(this).val();
			$('input[name="swap_settings[bg_type]"]').each(function () {
				this.checked = ($(this).val() === val);
				$(this).closest('.swap-mode-btn').toggleClass('active', this.checked);
			});
			$('.swap-bg-mode-content').hide();
			$('.swap-bg-mode-content[data-mode="' + val + '"]').show();
			updateBackgroundPreview();
		});

		// Sync solid background color
		$(document).on('input', '.swap-bg-color-sync', function () {
			var val = $(this).val();
			$('.swap-bg-color-sync').not(this).val(val);
			$('.swap-bg-hex-sync').val(val);
			updateBackgroundPreview();
		});
		$(document).on('input', '.swap-bg-hex-sync', function () {
			var val = $(this).val();
			$('.swap-bg-hex-sync').not(this).val(val);
			if (/^#[0-9a-fA-F]{6}$/.test(val)) {
				$('.swap-bg-color-sync').val(val);
				updateBackgroundPreview();
			}
		});

		// Sync gradient colors and angle
		$(document).on('input', '.swap-bg-grad-start-sync', function () {
			$('.swap-bg-grad-start-sync').not(this).val($(this).val());
			updateBackgroundPreview();
		});
		$(document).on('input', '.swap-bg-grad-end-sync', function () {
			$('.swap-bg-grad-end-sync').not(this).val($(this).val());
			updateBackgroundPreview();
		});
		$(document).on('input', '.swap-bg-angle-sync', function () {
			$('.swap-bg-angle-sync').not(this).val($(this).val());
			updateBackgroundPreview();
		});

		// Sync image URL and handling uploads
		var bg_file_frame;
		$(document).on('click', '.swap-bg-image-upload', function (e) {
			e.preventDefault();
			var $this = $(this);

			if (bg_file_frame) { bg_file_frame.open(); return; }

			if (typeof wp !== 'undefined' && wp.media) {
				bg_file_frame = wp.media.frames.bg_file_frame = wp.media({
					title: 'Select Background Image',
					button: { text: 'Use this image' },
					multiple: false
				});

				bg_file_frame.on('select', function () {
					var attachment = bg_file_frame.state().get('selection').first().toJSON();

					// Update all hidden inputs
					$('.swap-bg-image-url-sync').val(attachment.url).trigger('change');

					// Update all previews
					$('.swap-image-preview').css('background-image', 'url(' + attachment.url + ')').show();

					// Show display settings
					$('.swap-image-display-settings').show();

					updateBackgroundPreview();
				});

				bg_file_frame.open();
			}
		});

		// Remove background image
		$(document).on('click', '.swap-remove-image', function (e) {
			e.preventDefault();
			e.stopPropagation();
			$('.swap-bg-image-url-sync').val('').trigger('change');
			$('.swap-image-preview').hide().css('background-image', '');

			// Hide display settings
			$('.swap-image-display-settings').hide();
			updateBackgroundPreview();
		});

		// Sync image URL hidden input changes
		$(document).on('change', '.swap-bg-image-url-sync', function () {
			var val = $(this).val();
			$('.swap-bg-image-url-sync').not(this).val(val);
			updateBackgroundPreview();
		});

		// Helper to sync custom dropdown UI across tabs
		function syncCustomDropdownUI(inputClass, val) {
			$('.' + inputClass).each(function () {
				var $input = $(this);
				if ($input.val() !== val) {
					$input.val(val);
				}
				var $dd = $input.closest('.swap-custom-dropdown');
				if ($dd.length) {
					var $option = $dd.find('.swap-dd-options li[data-value="' + val + '"]');
					if ($option.length) {
						var text = $option.clone().children().remove().end().text().trim();
						$dd.find('.swap-dd-text').text(text);
						$dd.find('.swap-dd-options li').removeClass('selected');
						$dd.find('.swap-dd-options li .dashicons-yes').remove();
						$option.addClass('selected').append('<span class="dashicons dashicons-yes"></span>');
					}
				}
			});
		}

		// Sync image size and position
		$(document).on('change', '.swap-bg-image-size-sync', function () {
			var val = $(this).val();
			syncCustomDropdownUI('swap-bg-image-size-sync', val);
			updateBackgroundPreview();
		});
		$(document).on('change', '.swap-bg-image-position-sync', function () {
			var val = $(this).val();
			syncCustomDropdownUI('swap-bg-image-position-sync', val);
			updateBackgroundPreview();
		});
	})();

	// ============================================================
	// Freemium Locks Logic
	// ============================================================
	if (typeof swap_vars !== 'undefined' && swap_vars.isPro === false) {
		// Prevent any interaction on locked items just in case CSS pointer-events is bypassed
		$(document).on('click mousedown keydown', '.swap-pro-locked', function (e) {
			e.preventDefault();
			e.stopPropagation();
			return false;
		});
	}

});
