(function ($) {
	'use strict';

	if (typeof newsai_vars === 'undefined' || !newsai_vars.ai_active) {
		return;
	}
	if (newsai_vars.features && newsai_vars.features.floating_ai_menu === false) {
		return;
	}

	var __ = (typeof wp !== 'undefined' && wp.i18n && typeof wp.i18n.__ === 'function')
		? function (text) { return wp.i18n.__(text, 'newsroom-ai-assistant'); }
		: function (text) { return text; };

	var MIN_CHARS = 12;
	var MAX_CHARS = 1400;
	var SHOW_DELAY = 60;
	var HIDE_DELAY = 300;
	var GUTENBERG_SELECTOR = [
		'.edit-post-visual-editor',
		'.editor-visual-editor',
		'.editor-canvas',
		'.block-editor-writing-flow',
		'.editor-styles-wrapper',
		'.block-editor-block-list__layout',
		'.wp-block-post-content'
	].join(', ');
	var CLASSIC_SELECTOR = '#wp-content-wrap, #postdivrich, #content, #wp-content-editor-container, .mce-content-body';

	var $bar = null;
	var showTimer = null;
	var hideTimer = null;
	var lastSelection = '';
	var storedRange = null;
	var storedBookmark = null;
	var storedEditorId = '';
	var busy = false;
	var userInteracted = false;
	var bootTs = Date.now();
	var barInteracting = false;
	var gutenbergSavedText = '';
	var gutenbergSavedRange = null;
	var gutenbergStoredStoreSel = null;
	var escDismissTs = 0;

	function dismissBarByEscape() {
		escDismissTs = Date.now();
		hideBar(true);
		var ed = getActiveTinyMCE();
		if (ed) {
			try {
				ed.selection.collapse();
			} catch (eCol) {
				/* no-op */
			}
		}
		var ta = document.getElementById('content');
		if (ta && typeof ta.selectionStart === 'number') {
			var pos = ta.selectionStart;
			ta.selectionStart = pos;
			ta.selectionEnd = pos;
		}
		try {
			var sel = window.getSelection();
			if (sel && sel.removeAllRanges) {
				sel.removeAllRanges();
			}
		} catch (eSel) {
			/* no-op */
		}
	}

	function isEscapeKey(e) {
		if (!e) {
			return false;
		}
		return e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27;
	}

	function recentlyDismissedByEscape() {
		return (Date.now() - escDismissTs) < 450;
	}

	function isContentEditableArea(node) {
		if (!node || !node.closest) {
			return false;
		}
		var editable = node.closest('[contenteditable], .block-editor-rich-text__editable, .rich-text');
		if (!editable) {
			return false;
		}
		var flag = editable.getAttribute ? editable.getAttribute('contenteditable') : '';
		return flag !== 'false';
	}

	function gutenbergWritingSurface() {
		return document.querySelector(
			'.interface-interface-skeleton__content, .edit-post-layout, .editor-post-text-editor'
		);
	}

	function nodeInSidebarChrome(node) {
		if (!node || !node.closest) {
			return false;
		}
		return !!node.closest(
			'#newsai_sidebar, .nros-ai-float, .interface-interface-skeleton__sidebar, ' +
			'.edit-post-sidebar, .edit-post-sidebar__panel'
		);
	}

	function nodeInGutenbergWritingArea(node) {
		if (!node || nodeInSidebarChrome(node)) {
			return false;
		}
		if (isContentEditableArea(node)) {
			return true;
		}
		if (node.closest(GUTENBERG_SELECTOR)) {
			return true;
		}
		var surface = gutenbergWritingSurface();
		return !!(surface && surface.contains(node));
	}

	function selectionDocuments() {
		var docs = [document];
		var seen = { document: true };
		var iframes = document.querySelectorAll(
			'.edit-post-visual-editor iframe, .editor-canvas iframe, iframe.editor-canvas__iframe, iframe[name="editor-canvas"]'
		);
		for (var i = 0; i < iframes.length; i++) {
			var frameDoc = null;
			try {
				frameDoc = iframes[i].contentDocument;
			} catch (eFrame) {
				frameDoc = null;
			}
			if (frameDoc && !seen[frameDoc]) {
				seen[frameDoc] = true;
				docs.push(frameDoc);
			}
		}
		return docs;
	}

	function readSelectionFromDocument(doc) {
		if (!doc || typeof doc.getSelection !== 'function') {
			return null;
		}
		var sel = doc.getSelection();
		if (!sel || sel.isCollapsed || !sel.rangeCount) {
			return null;
		}
		if (!nodeInGutenbergWritingArea(nodeFromSelection(sel))) {
			return null;
		}
		var text = normalizeSelectionText(sel.toString());
		if (text.length < MIN_CHARS || text.length > MAX_CHARS) {
			return null;
		}
		return { text: text, editor: null, sel: sel, doc: doc };
	}

	function readGutenbergSelection() {
		var docs = selectionDocuments();
		var i;
		for (i = 0; i < docs.length; i++) {
			var pack = readSelectionFromDocument(docs[i]);
			if (pack) {
				return pack;
			}
		}
		return null;
	}

	function clientIdFromRange(range) {
		if (!range || !range.startContainer) {
			return null;
		}
		var node = range.startContainer.nodeType === 3
			? range.startContainer.parentElement
			: range.startContainer;
		if (!node || !node.closest) {
			return null;
		}
		var blockEl = node.closest('[data-block]');
		return blockEl ? blockEl.getAttribute('data-block') : null;
	}

	function captureGutenbergStoreSelection() {
		try {
			if (typeof wp === 'undefined' || !wp.data) {
				return null;
			}
			var bs = wp.data.select('core/block-editor');
			if (!bs || typeof bs.getSelectionStart !== 'function' || typeof bs.getSelectionEnd !== 'function') {
				return null;
			}
			var start = bs.getSelectionStart();
			var end = bs.getSelectionEnd();
			if (!start || !end || !start.clientId || start.clientId !== end.clientId) {
				return null;
			}
			if (typeof start.offset !== 'number' || typeof end.offset !== 'number') {
				return null;
			}
			if (start.offset === end.offset) {
				return null;
			}
			return {
				clientId: start.clientId,
				attributeKey: start.attributeKey || 'content',
				startOffset: Math.min(start.offset, end.offset),
				endOffset: Math.max(start.offset, end.offset)
			};
		} catch (eStore) {
			return null;
		}
	}

	function resolveGutenbergAttributeKey(block, preferred) {
		if (!block || !block.attributes) {
			return 'content';
		}
		if (preferred && block.attributes[preferred] !== undefined) {
			return preferred;
		}
		if (block.attributes.content !== undefined) {
			return 'content';
		}
		if (block.attributes.values !== undefined) {
			return 'values';
		}
		return preferred || 'content';
	}

	function replaceGutenbergSelection(text) {
		if (typeof wp === 'undefined' || !wp.data || !wp.richText) {
			return false;
		}
		var richText = wp.richText;
		var select = wp.data.select('core/block-editor');
		var dispatch = wp.data.dispatch('core/block-editor');
		if (!select || !dispatch || typeof dispatch.updateBlockAttributes !== 'function') {
			return false;
		}

		var storeSel = gutenbergStoredStoreSel;
		var clientId = storeSel ? storeSel.clientId : null;
		var attrKey = storeSel ? storeSel.attributeKey : 'content';
		var startOff = storeSel ? storeSel.startOffset : null;
		var endOff = storeSel ? storeSel.endOffset : null;

		if (!clientId && gutenbergSavedRange) {
			clientId = clientIdFromRange(gutenbergSavedRange);
		}
		if (!clientId && storedRange) {
			clientId = clientIdFromRange(storedRange);
		}
		if (!clientId) {
			return false;
		}

		var block = select.getBlock(clientId);
		if (!block || !block.attributes) {
			return false;
		}

		attrKey = resolveGutenbergAttributeKey(block, attrKey);
		var raw = block.attributes[attrKey];
		if (raw === undefined || raw === null) {
			return false;
		}

		var value;
		if (typeof raw === 'string') {
			value = richText.create({ html: raw });
		} else if (typeof raw === 'object' && raw.text !== undefined) {
			value = raw;
		} else {
			value = richText.create({ html: String(raw) });
		}

		if (startOff === null || endOff === null) {
			var plain = richText.getTextContent(value);
			var needle = lastSelection || gutenbergSavedText;
			if (!needle) {
				return false;
			}
			var idx = plain.indexOf(needle);
			if (idx === -1 && needle.length > 48) {
				idx = plain.indexOf(needle.substring(0, 48));
			}
			if (idx === -1) {
				return false;
			}
			startOff = idx;
			endOff = idx + needle.length;
		}

		var newValue;
		try {
			newValue = richText.insert(value, text, startOff, endOff);
		} catch (eInsert) {
			return false;
		}

		var update = {};
		if (typeof raw === 'string') {
			update[attrKey] = richText.toHTMLString({ value: newValue });
		} else {
			update[attrKey] = newValue;
		}

		try {
			dispatch.updateBlockAttributes(clientId, update);
			return true;
		} catch (eUpdate) {
			return false;
		}
	}

	function persistGutenbergSelection(pack) {
		if (!pack || !pack.text) {
			return;
		}
		gutenbergSavedText = pack.text;
		lastSelection = pack.text;
		storedEditorId = '';
		storedBookmark = null;
		if (pack.sel && pack.sel.rangeCount) {
			try {
				gutenbergSavedRange = pack.sel.getRangeAt(0).cloneRange();
				storedRange = gutenbergSavedRange.cloneRange();
			} catch (eRange) {
				gutenbergSavedRange = null;
				storedRange = null;
			}
		}
		var storeSel = captureGutenbergStoreSelection();
		if (storeSel) {
			gutenbergStoredStoreSel = storeSel;
		}
	}

	function restoreGutenbergSavedSelection() {
		if (gutenbergSavedText.length >= MIN_CHARS) {
			lastSelection = gutenbergSavedText;
		}
		if (gutenbergSavedRange) {
			storedRange = gutenbergSavedRange;
		}
		return lastSelection.length >= MIN_CHARS;
	}

	function toast(msg) {
		if (typeof window.nrosAiFloatToast === 'function') {
			window.nrosAiFloatToast(msg);
		}
	}

	window.nrosAiFloatToast = function (message) {
		message = String(message || '');
		if (!message) {
			return;
		}
		var $t = $('<div class="nros-toast"></div>').text(message);
		$('body').append($t);
		window.setTimeout(function () {
			$t.fadeOut(220, function () {
				$t.remove();
			});
		}, 2200);
	};

	function markInteracted() {
		userInteracted = true;
	}

	function isGutenberg() {
		return document.body.classList.contains('block-editor-page');
	}

	function getTitle() {
		if (typeof nrosGetTitle === 'function') {
			return String(nrosGetTitle() || '');
		}
		return String($('#title, .editor-post-title__input').val() || '');
	}

	function getContent() {
		if (typeof nrosGetContent === 'function') {
			return String(nrosGetContent() || '');
		}
		return String($('#content').val() || '');
	}

	function resolvePostId() {
		if (typeof nrosResolveEditorPostId === 'function') {
			return parseInt(nrosResolveEditorPostId(), 10) || 0;
		}
		return parseInt(newsai_vars.post_id, 10) || 0;
	}

	function nodeFromSelection(sel) {
		if (!sel || !sel.anchorNode) {
			return null;
		}
		var node = sel.anchorNode;
		return node.nodeType === 3 ? node.parentElement : node;
	}

	function nodeInEditor(node) {
		if (!node || !node.closest) {
			return false;
		}
		if (isGutenberg()) {
			return nodeInGutenbergWritingArea(node);
		}
		if (nodeInSidebarChrome(node)) {
			return false;
		}
		return !!node.closest(CLASSIC_SELECTOR);
	}

	function selectionInEditor(sel) {
		return nodeInEditor(nodeFromSelection(sel));
	}

	function normalizeSelectionText(raw) {
		return String(raw || '').replace(/\s+/g, ' ').trim();
	}

	function getActiveTinyMCE() {
		if (typeof tinymce === 'undefined') {
			return null;
		}
		if (storedEditorId) {
			var storedEd = tinymce.get(storedEditorId);
			if (storedEd && !storedEd.isHidden()) {
				return storedEd;
			}
		}
		var ed = tinymce.activeEditor;
		if (ed && !ed.isHidden()) {
			return ed;
		}
		ed = tinymce.get('content');
		if (ed && !ed.isHidden()) {
			return ed;
		}
		return null;
	}

	function getTinyMCEIframe(ed) {
		if (!ed) {
			return null;
		}
		if (ed.iframeElement) {
			return ed.iframeElement;
		}
		var container = typeof ed.getContentAreaContainer === 'function' ? ed.getContentAreaContainer() : null;
		return container ? container.querySelector('iframe') : null;
	}

	function clientRectFromTinyMCE(ed) {
		if (!ed) {
			return null;
		}
		var rect = null;
		try {
			rect = ed.selection.getRng().getBoundingClientRect();
		} catch (eTmce) {
			return null;
		}
		if (!rect || (rect.width === 0 && rect.height === 0)) {
			return null;
		}
		var iframe = getTinyMCEIframe(ed);
		if (!iframe) {
			return rect;
		}
		var iframeRect = iframe.getBoundingClientRect();
		return {
			top: iframeRect.top + rect.top,
			left: iframeRect.left + rect.left,
			bottom: iframeRect.top + rect.bottom,
			right: iframeRect.left + rect.right,
			width: rect.width,
			height: rect.height
		};
	}

	function getTinyMCESelection() {
		var ed = getActiveTinyMCE();
		if (!ed) {
			return null;
		}
		var text = normalizeSelectionText(ed.selection.getContent({ format: 'text' }));
		if (text.length < MIN_CHARS || text.length > MAX_CHARS) {
			return null;
		}
		return { text: text, editor: ed, sel: null };
	}

	function tinyMCESelectionMatches(ed, expectedText) {
		if (!ed || ed.selection.isCollapsed()) {
			return false;
		}
		return normalizeSelectionText(ed.selection.getContent({ format: 'text' })) === normalizeSelectionText(expectedText);
	}

	function selectPlainTextInTinyMCE(ed, searchText) {
		if (!ed || !searchText) {
			return false;
		}
		var doc = ed.getDoc();
		var body = ed.getBody();
		if (!doc || !body) {
			return false;
		}

		var needle = String(searchText);
		var walker = doc.createTreeWalker(body, NodeFilter.SHOW_TEXT, null, false);
		var chunks = [];
		var node;
		while ((node = walker.nextNode())) {
			chunks.push({ node: node, text: node.textContent, len: node.textContent.length });
		}
		if (!chunks.length) {
			return false;
		}

		var full = '';
		var i;
		for (i = 0; i < chunks.length; i++) {
			chunks[i].start = full.length;
			full += chunks[i].text;
		}

		var idx = full.indexOf(needle);
		if (idx === -1 && needle.length > 48) {
			idx = full.indexOf(needle.substring(0, 48));
			if (idx !== -1) {
				needle = full.substring(idx, Math.min(idx + searchText.length, full.length));
			}
		}
		if (idx === -1) {
			return false;
		}

		var endIdx = idx + needle.length;
		var startNode = null;
		var startOff = 0;
		var endNode = null;
		var endOff = 0;

		for (i = 0; i < chunks.length; i++) {
			var chunk = chunks[i];
			if (!startNode && idx >= chunk.start && idx < chunk.start + chunk.len) {
				startNode = chunk.node;
				startOff = idx - chunk.start;
			}
			if (endIdx >= chunk.start && endIdx <= chunk.start + chunk.len) {
				endNode = chunk.node;
				endOff = endIdx - chunk.start;
				break;
			}
		}

		if (!startNode || !endNode) {
			return false;
		}

		try {
			var rng = doc.createRange();
			rng.setStart(startNode, startOff);
			rng.setEnd(endNode, endOff);
			ed.selection.setRng(rng);
			return !ed.selection.isCollapsed();
		} catch (eSelect) {
			return false;
		}
	}

	function restoreTinyMCESelection(ed, expectedText) {
		if (!ed) {
			return false;
		}
		ed.focus();
		if (storedBookmark) {
			try {
				ed.selection.moveToBookmark(storedBookmark);
			} catch (eBookmark) {
				/* fall through */
			}
		}
		if (expectedText && tinyMCESelectionMatches(ed, expectedText)) {
			return true;
		}
		if (expectedText && selectPlainTextInTinyMCE(ed, expectedText)) {
			try {
				storedBookmark = ed.selection.getBookmark(2, true);
			} catch (eSave) {
				/* keep existing bookmark */
			}
			return !ed.selection.isCollapsed();
		}
		return false;
	}

	function replaceTinyMCESelection(ed, newText) {
		var findText = lastSelection || '';
		if (!findText) {
			return false;
		}
		var replaced = false;
		ed.undoManager.transact(function () {
			if (!restoreTinyMCESelection(ed, findText)) {
				throw new Error('selection_not_found');
			}
			var rng = ed.selection.getRng();
			if (rng.collapsed) {
				throw new Error('selection_not_found');
			}
			rng.deleteContents();
			ed.selection.setContent(newText, { format: 'text' });
			replaced = true;
		});
		if (typeof ed.nodeChanged === 'function') {
			ed.nodeChanged();
		}
		if (typeof ed.fire === 'function') {
			ed.fire('change');
		}
		return replaced;
	}

	function replaceTextareaSelection(newText) {
		var ta = document.getElementById('content');
		if (!ta) {
			return false;
		}
		var start = ta.selectionStart;
		var end = ta.selectionEnd;
		var val = String(ta.value || '');
		if ((end - start) < MIN_CHARS && lastSelection) {
			var idx = val.indexOf(lastSelection);
			if (idx === -1 && lastSelection.length > 48) {
				idx = val.indexOf(lastSelection.substring(0, 48));
			}
			if (idx !== -1) {
				start = idx;
				end = idx + lastSelection.length;
			}
		}
		if (end <= start) {
			return false;
		}
		ta.value = val.substring(0, start) + newText + val.substring(end);
		ta.selectionStart = start;
		ta.selectionEnd = start + newText.length;
		try {
			ta.dispatchEvent(new Event('input', { bubbles: true }));
		} catch (eInput) {
			/* no-op */
		}
		return true;
	}

	function readNativeSelection() {
		var sel = window.getSelection();
		if (!sel || sel.isCollapsed || !selectionInEditor(sel)) {
			return null;
		}
		var text = normalizeSelectionText(sel.toString());
		if (text.length < MIN_CHARS || text.length > MAX_CHARS) {
			return null;
		}
		return { text: text, editor: null, sel: sel };
	}

	function getSelectionPack() {
		if (!isGutenberg()) {
			var tmce = getTinyMCESelection();
			if (tmce) {
				return tmce;
			}
			return readNativeSelection();
		}
		return readGutenbergSelection();
	}

	function captureSelectionState() {
		var pack = getSelectionPack();
		if (pack) {
			lastSelection = pack.text;
			if (pack.editor) {
				storedEditorId = pack.editor.id || 'content';
				try {
					storedBookmark = pack.editor.selection.getBookmark(2, true);
				} catch (eBookmark) {
					storedBookmark = null;
				}
				storedRange = null;
				gutenbergSavedText = '';
				gutenbergSavedRange = null;
			} else if (pack.sel) {
				if (isGutenberg()) {
					persistGutenbergSelection(pack);
				} else {
					storedEditorId = '';
					storedBookmark = null;
					try {
						storedRange = pack.sel.getRangeAt(0).cloneRange();
					} catch (eRange) {
						storedRange = null;
					}
				}
			}
			return true;
		}
		if (isGutenberg() && restoreGutenbergSavedSelection()) {
			return true;
		}
		return false;
	}

	function clearSelectionState() {
		lastSelection = '';
		storedRange = null;
		storedBookmark = null;
		storedEditorId = '';
		gutenbergSavedText = '';
		gutenbergSavedRange = null;
		gutenbergStoredStoreSel = null;
	}

	function ensureBar() {
		if ($bar && $bar.length) {
			return $bar;
		}
		var html = ''
			+ '<div class="nros-ai-float" id="nros-ai-float" role="toolbar" aria-label="' + escAttr(__('AI selection tools')) + '">'
			+ '<button type="button" class="nros-ai-float__btn" data-edit="rewrite">' + escHtml(__('Rewrite')) + '</button>'
			+ '<span class="nros-ai-float__sep" aria-hidden="true"></span>'
			+ '<button type="button" class="nros-ai-float__btn" data-edit="shorten">' + escHtml(__('Shorten')) + '</button>'
			+ '<button type="button" class="nros-ai-float__btn" data-edit="expand">' + escHtml(__('Expand')) + '</button>'
			+ '<button type="button" class="nros-ai-float__btn" data-edit="simplify">' + escHtml(__('Simplify')) + '</button>'
			+ '</div>';
		$bar = $(html).appendTo(document.body);
		$bar.on('mousedown pointerdown', function (e) {
			barInteracting = true;
			e.stopPropagation();
		});
		$bar.on('mousedown', '.nros-ai-float__btn', function (e) {
			e.preventDefault();
			e.stopPropagation();
			var edBtn = getActiveTinyMCE();
			if (edBtn && storedBookmark) {
				try {
					edBtn.selection.moveToBookmark(storedBookmark);
				} catch (eBm) {
					/* rely on stored text fallback */
				}
			}
		});
		$bar.on('mouseup pointerup', function () {
			window.setTimeout(function () {
				barInteracting = false;
			}, 120);
		});
		$bar.on('click', '.nros-ai-float__btn', function (e) {
			e.preventDefault();
			e.stopPropagation();
			runEdit(String($(this).data('edit') || ''));
		});
		return $bar;
	}

	function escHtml(str) {
		return String(str || '')
			.replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;');
	}

	function escAttr(str) {
		return escHtml(str).replace(/"/g, '&quot;');
	}

	function restoreSelectionRange() {
		if (!storedRange) {
			return false;
		}
		var doc = storedRange.startContainer && storedRange.startContainer.ownerDocument
			? storedRange.startContainer.ownerDocument
			: document;
		var sel = doc.getSelection ? doc.getSelection() : window.getSelection();
		if (!sel) {
			return false;
		}
		sel.removeAllRanges();
		sel.addRange(storedRange);
		return true;
	}

	function hideBar(clearState) {
		clearTimeout(showTimer);
		clearTimeout(hideTimer);
		showTimer = null;
		hideTimer = null;
		if ($bar) {
			$bar.removeClass('is-visible is-busy');
		}
		if (clearState === true || clearState === 'force') {
			clearSelectionState();
		} else if (clearState !== false && !isGutenberg()) {
			clearSelectionState();
		}
	}

	function scheduleHide() {
		clearTimeout(hideTimer);
		hideTimer = setTimeout(function () {
			hideTimer = null;
			if (busy || barInteracting) {
				return;
			}
			if (!getSelectionPack() && !lastSelection) {
				hideBar(true);
				return;
			}
			if (!getSelectionPack() && lastSelection && $bar && $bar.hasClass('is-visible')) {
				$bar.removeClass('is-visible');
			}
		}, HIDE_DELAY);
	}

	function selectionRect(pack) {
		if (pack && pack.editor) {
			return clientRectFromTinyMCE(pack.editor);
		}
		if (storedRange) {
			try {
				return storedRange.getBoundingClientRect();
			} catch (eStored) {
				/* fall through */
			}
		}
		if (pack && pack.sel && pack.sel.rangeCount) {
			try {
				return pack.sel.getRangeAt(0).getBoundingClientRect();
			} catch (eNative) {
				/* fall through */
			}
		}
		var sel = window.getSelection();
		if (sel && sel.rangeCount) {
			try {
				return sel.getRangeAt(0).getBoundingClientRect();
			} catch (eWin) {
				return null;
			}
		}
		return null;
	}

	function positionBar(pack) {
		var rect = selectionRect(pack);
		if (!rect || (rect.width === 0 && rect.height === 0)) {
			return false;
		}
		var bar = ensureBar();
		var top = rect.top - bar.outerHeight() - 8;
		var left = rect.left + (rect.width / 2) - (bar.outerWidth() / 2);
		if (top < 8) {
			top = rect.bottom + 8;
		}
		left = Math.max(8, Math.min(left, window.innerWidth - bar.outerWidth() - 8));
		bar.css({ top: top + 'px', left: left + 'px' }).addClass('is-visible');
		return true;
	}

	function tryShowBar() {
		if (busy || isGutenberg()) {
			return;
		}
		if (recentlyDismissedByEscape()) {
			return;
		}
		if (!userInteracted && (Date.now() - bootTs) < 800) {
			return;
		}
		clearTimeout(hideTimer);
		hideTimer = null;

		var pack = getSelectionPack();
		if (!pack) {
			return;
		}
		captureSelectionState();
		positionBar(pack);
	}

	function scheduleShow() {
		if (isGutenberg()) {
			captureSelectionState();
			return;
		}
		clearTimeout(showTimer);
		showTimer = setTimeout(function () {
			showTimer = null;
			tryShowBar();
		}, SHOW_DELAY);
	}

	function onPointerUp(e) {
		if (isEscapeKey(e)) {
			return;
		}
		markInteracted();
		if (busy) {
			return;
		}
		if (isGutenberg()) {
			captureSelectionState();
			return;
		}
		scheduleShow();
		window.setTimeout(tryShowBar, 0);
		window.setTimeout(tryShowBar, 120);
	}

	function onSelectionChange() {
		if (busy || barInteracting) {
			return;
		}
		if (isGutenberg()) {
			captureSelectionState();
			return;
		}
		if (!userInteracted) {
			return;
		}
		var pack = getSelectionPack();
		if (pack) {
			clearTimeout(hideTimer);
			hideTimer = null;
			captureSelectionState();
			scheduleShow();
			return;
		}
		if ($bar && $bar.hasClass('is-visible')) {
			scheduleHide();
		}
	}

	function replaceSelection(text) {
		text = String(text || '').trim();
		if (!text) {
			return false;
		}

		if (isGutenberg()) {
			return replaceGutenbergSelection(text);
		}

		var ed = getActiveTinyMCE();
		if (ed) {
			try {
				return replaceTinyMCESelection(ed, text);
			} catch (eTiny) {
				return false;
			}
		}

		if (replaceTextareaSelection(text)) {
			return true;
		}

		if (!restoreSelectionRange()) {
			return false;
		}

		var rangeDoc = storedRange && storedRange.startContainer && storedRange.startContainer.ownerDocument
			? storedRange.startContainer.ownerDocument
			: document;

		try {
			if (rangeDoc.execCommand && rangeDoc.execCommand('insertText', false, text)) {
				return true;
			}
		} catch (eDocCmd) {
			/* fall through */
		}

		try {
			if (document.execCommand('insertText', false, text)) {
				return true;
			}
		} catch (eCmd) {
			/* fall through */
		}

		try {
			var sel = window.getSelection();
			if (!sel || !sel.rangeCount) {
				return false;
			}
			var range = sel.getRangeAt(0);
			range.deleteContents();
			range.insertNode(document.createTextNode(text));
			range.collapse(false);
			sel.removeAllRanges();
			sel.addRange(range);
			return true;
		} catch (eRange) {
			return false;
		}
	}

	function runEdit(action) {
		if (busy) {
			return;
		}
		captureSelectionState();
		if (!lastSelection && isGutenberg()) {
			restoreGutenbergSavedSelection();
		}
		if (!lastSelection) {
			toast(__('Highlight at least 12 characters first.'));
			return;
		}
		var allowed = { rewrite: 1, shorten: 1, expand: 1, simplify: 1 };
		if (!allowed[action]) {
			return;
		}
		busy = true;
		if (!isGutenberg()) {
			ensureBar().addClass('is-busy');
			var edBefore = getActiveTinyMCE();
			if (edBefore && lastSelection && tinyMCESelectionMatches(edBefore, lastSelection)) {
				try {
					storedBookmark = edBefore.selection.getBookmark(2, true);
				} catch (ePre) {
					/* keep prior bookmark */
				}
			}
		} else if ($bar) {
			$bar.addClass('is-busy');
		}
		$.post(newsai_vars.ajax_url, {
			action: 'newsai_ai_selection_edit',
			nonce: newsai_vars.nonce,
			post_id: resolvePostId(),
			title: getTitle(),
			content: getContent(),
			selection: lastSelection,
			edit_action: action
		})
			.done(function (resp) {
				var payload = (resp && resp.data) ? resp.data : {};
				var result = (payload && payload.data) ? payload.data : payload;
				var next = result && result.text ? String(result.text).trim() : '';
				if (!resp || !resp.success || !next) {
					var errMsg = (payload && payload.message) ? String(payload.message) : '';
					toast(errMsg ? errMsg : __('AI could not edit the selection.'));
					return;
				}
				if (!replaceSelection(next)) {
					toast(__('Could not replace selection in the editor.'));
					return;
				}
				toast(__('Selection updated.'));
				clearSelectionState();
				if (!isGutenberg()) {
					hideBar(false);
				} else if ($bar) {
					$bar.removeClass('is-visible is-busy');
				}
				if (typeof nrosTriggerUpdate === 'function') {
					nrosTriggerUpdate(true);
				}
			})
			.fail(function (xhr) {
				var msg = __('AI request failed.');
				try {
					var err = xhr && xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message;
					if (err) {
						msg = String(err);
					}
				} catch (eFail) {
					/* keep default */
				}
				toast(msg);
			})
			.always(function () {
				busy = false;
				if ($bar) {
					$bar.removeClass('is-busy');
				}
			});
	}

	function clickInsideEditor(target) {
		if (!target || !target.closest) {
			return false;
		}
		if (isGutenberg()) {
			return !!(target.closest(GUTENBERG_SELECTOR) || isContentEditableArea(target));
		}
		return !!target.closest(CLASSIC_SELECTOR);
	}

	function isGutenbergUiChrome(target) {
		if (!isGutenberg() || !target || !target.closest) {
			return false;
		}
		return !!target.closest(
			'.block-editor-block-toolbar, .block-editor-block-contextual-toolbar, ' +
			'.components-accessible-toolbar, .components-toolbar, .components-popover, ' +
			'.components-dropdown-menu__content, .components-menu-item, ' +
			'.edit-post-header, .interface-interface-skeleton__header'
		);
	}

	function onDocumentMouseDown(e) {
		markInteracted();
		if (busy) {
			return;
		}
		var target = e.target;
		if (target && target.closest && target.closest('.nros-ai-float')) {
			return;
		}
		if (isGutenbergUiChrome(target)) {
			return;
		}
		if (clickInsideEditor(target)) {
			return;
		}
		if (isGutenberg()) {
			if ($bar) {
				$bar.removeClass('is-visible');
			}
			return;
		}
		hideBar(true);
	}

	function bindTinyMCEEditor(ed) {
		if (!ed || ed.nrosAiFloatBound) {
			return;
		}
		ed.nrosAiFloatBound = true;
		ed.on('mouseup keyup', function (ev) {
			if (isEscapeKey(ev)) {
				dismissBarByEscape();
				return;
			}
			onPointerUp(ev);
		});
		var win = typeof ed.getWin === 'function' ? ed.getWin() : null;
		if (win) {
			if (!win.nrosAiFloatEscBound) {
				win.nrosAiFloatEscBound = true;
				win.addEventListener('keydown', function (e) {
					if (isEscapeKey(e)) {
						dismissBarByEscape();
					}
				}, true);
			}
			win.addEventListener('scroll', function () {
				if ($bar && $bar.hasClass('is-visible')) {
					tryShowBar();
				}
			}, true);
		}
	}

	function initTinyMCEHooks() {
		if (typeof tinymce === 'undefined') {
			return;
		}
		tinymce.on('AddEditor', function (e) {
			bindTinyMCEEditor(e.editor);
		});
		if (tinymce.editors && tinymce.editors.length) {
			for (var i = 0; i < tinymce.editors.length; i++) {
				bindTinyMCEEditor(tinymce.editors[i]);
			}
		}
		window.setTimeout(function () {
			bindTinyMCEEditor(tinymce.get('content'));
		}, 800);
		window.setTimeout(function () {
			bindTinyMCEEditor(tinymce.get('content'));
		}, 2500);
	}

	window.nrosAiFloatRunEdit = runEdit;
	window.nrosAiFloatCaptureSelection = captureSelectionState;
	window.nrosAiFloatGetSelection = function () {
		captureSelectionState();
		return String(lastSelection || gutenbergSavedText || '');
	};

	document.addEventListener('mouseup', onPointerUp, true);
	document.addEventListener('pointerup', onPointerUp, true);
	document.addEventListener('keyup', onPointerUp, true);
	document.addEventListener('selectionchange', onSelectionChange, false);
	document.addEventListener('mousedown', onDocumentMouseDown, true);

	document.addEventListener('keydown', function (e) {
		markInteracted();
		if (isEscapeKey(e)) {
			dismissBarByEscape();
		}
	}, true);

	window.addEventListener('scroll', function () {
		if ($bar && $bar.hasClass('is-visible')) {
			tryShowBar();
		}
	}, true);

	window.addEventListener('resize', function () {
		if ($bar && $bar.hasClass('is-visible')) {
			tryShowBar();
		}
	}, true);

	$(function () {
		if (!isGutenberg()) {
			initTinyMCEHooks();
			$(document).on('mouseup.nrosAiFloat keyup.nrosAiFloat', CLASSIC_SELECTOR, onPointerUp);
			$('#content').on('keydown.nrosAiFloat', function (e) {
				if (isEscapeKey(e)) {
					dismissBarByEscape();
				}
			});
			return;
		}
		$(document).on(
			'mouseup.nrosAiFloatGb keyup.nrosAiFloatGb',
			'.block-editor-rich-text__editable, .rich-text, [contenteditable], ' + GUTENBERG_SELECTOR,
			function () {
				markInteracted();
				captureSelectionState();
			}
		);
		document.addEventListener('selectionchange', function () {
			if (!isGutenberg() || busy || barInteracting) {
				return;
			}
			captureSelectionState();
		}, true);
	});

}(jQuery));
