/**
 * Dynamic Content editor UI: a trigger on every text field (textfield,
 * textarea and the TinyMCE WYSIWYG) that inserts a {{cafw:...}} token from a
 * styled source picker. When WPBakery's AI icon is present the trigger sits
 * right next to it.
 */
( function () {
	'use strict';

	var data = window.cafwDynamic || {};
	var sources = data.sources || [];
	var i18n = data.i18n || {};
	var openPop = null;

	function token( key, arg ) {
		arg = ( arg || '' ).trim();
		return arg ? '{{cafw:' + key + '|' + arg + '}}' : '{{cafw:' + key + '}}';
	}

	function fire( el ) {
		el.dispatchEvent( new Event( 'input', { bubbles: true } ) );
		el.dispatchEvent( new Event( 'change', { bubbles: true } ) );
	}

	function insertIntoField( input, value ) {
		var start = input.selectionStart;
		var end = input.selectionEnd;
		var current = input.value;
		if ( typeof start === 'number' ) {
			input.value = current.slice( 0, start ) + value + current.slice( end );
			var pos = start + value.length;
			try {
				input.setSelectionRange( pos, pos );
			} catch ( e ) {}
		} else {
			input.value = current + value;
		}
		fire( input );
		input.focus();
	}

	/**
	 * Insert a token into a field context. For the WYSIWYG in Visual mode the
	 * token goes into the active TinyMCE editor; otherwise straight into the
	 * underlying textarea/input.
	 */
	function insertToken( ctx, value ) {
		if ( ctx.html && window.tinymce && ctx.id ) {
			var ed = window.tinymce.get( ctx.id );
			if ( ed && ! ed.isHidden() ) {
				ed.execCommand( 'mceInsertContent', false, value );
				ed.save();
				fire( ctx.el );
				return;
			}
		}
		insertIntoField( ctx.el, value );
	}

	function closePop() {
		if ( openPop ) {
			openPop.parentNode.removeChild( openPop );
			openPop = null;
			document.removeEventListener( 'mousedown', onDocDown, true );
			document.removeEventListener( 'keydown', onKey, true );
		}
	}

	function onDocDown( e ) {
		if ( openPop && ! openPop.contains( e.target ) && ! e.target.closest( '.cafw-dyn-btn' ) ) {
			closePop();
		}
	}

	function onKey( e ) {
		if ( e.key === 'Escape' ) {
			closePop();
		}
	}

	function showArg( pop, key, item, ctx ) {
		var old = pop.querySelector( '.cafw-dyn-arg' );
		if ( old ) {
			old.parentNode.removeChild( old );
		}
		var wrap = document.createElement( 'div' );
		wrap.className = 'cafw-dyn-arg';
		var lbl = document.createElement( 'label' );
		lbl.textContent = item.arg_label;
		var inp = document.createElement( 'input' );
		inp.type = 'text';
		inp.placeholder = item.placeholder || '';
		var go = document.createElement( 'button' );
		go.type = 'button';
		go.className = 'cafw-dyn-insert';
		go.textContent = i18n.insert || 'Insert';
		function doInsert() {
			var arg = inp.value.trim();
			if ( item.arg_require && ! arg ) {
				inp.focus();
				return;
			}
			insertToken( ctx, token( key, arg ) );
			closePop();
		}
		go.addEventListener( 'click', doInsert );
		inp.addEventListener( 'keydown', function ( e ) {
			if ( e.key === 'Enter' ) {
				e.preventDefault();
				doInsert();
			}
		} );
		wrap.appendChild( lbl );
		wrap.appendChild( inp );
		wrap.appendChild( go );
		pop.appendChild( wrap );
		inp.focus();
	}

	function buildPop( ctx, btn ) {
		closePop();
		var pop = document.createElement( 'div' );
		pop.className = 'cafw-dyn-pop';

		var head = document.createElement( 'div' );
		head.className = 'cafw-dyn-pop__head';
		head.textContent = i18n.title || 'Dynamic content';
		pop.appendChild( head );

		var list = document.createElement( 'div' );
		list.className = 'cafw-dyn-pop__list';
		sources.forEach( function ( group ) {
			var gl = document.createElement( 'div' );
			gl.className = 'cafw-dyn-group__label';
			gl.textContent = group.label;
			list.appendChild( gl );
			Object.keys( group.items ).forEach( function ( key ) {
				var item = group.items[ key ];
				var row = document.createElement( 'button' );
				row.type = 'button';
				row.className = 'cafw-dyn-item';
				row.textContent = item.label;
				if ( group.pro ) {
					row.classList.add( 'cafw-dyn-item--pro' );
					var badge = document.createElement( 'span' );
					badge.className = 'cafw-dyn-pro';
					badge.innerHTML = '<svg viewBox="0 0 24 24" width="11" height="11" fill="currentColor" aria-hidden="true"><path d="M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm3 8H9V6a3 3 0 0 1 6 0v3z"/></svg>' + ( i18n.pro || 'Pro' );
					row.appendChild( badge );
					row.addEventListener( 'click', function ( e ) {
						e.preventDefault();
						if ( data.upgradeUrl ) {
							window.open( data.upgradeUrl, '_blank' );
						}
					} );
				} else {
					row.addEventListener( 'click', function ( e ) {
						e.preventDefault();
						if ( item.arg_label ) {
							showArg( pop, key, item, ctx );
						} else {
							insertToken( ctx, token( key, '' ) );
							closePop();
						}
					} );
				}
				list.appendChild( row );
			} );
		} );
		pop.appendChild( list );

		document.body.appendChild( pop );
		position( pop, btn );
		openPop = pop;
		document.addEventListener( 'mousedown', onDocDown, true );
		document.addEventListener( 'keydown', onKey, true );
	}

	function position( pop, btn ) {
		var r = btn.getBoundingClientRect();
		pop.style.position = 'fixed';
		pop.style.left = Math.max( 8, Math.min( r.left, window.innerWidth - pop.offsetWidth - 12 ) ) + 'px';
		var top = r.bottom + 6;
		if ( top + pop.offsetHeight > window.innerHeight - 8 ) {
			top = Math.max( 8, r.top - pop.offsetHeight - 6 );
		}
		pop.style.top = top + 'px';
	}

	function makeButton( ctx ) {
		var btn = document.createElement( 'button' );
		btn.type = 'button';
		btn.className = 'cafw-dyn-btn';
		btn.title = i18n.button || 'Insert dynamic content';
		btn.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" fill="currentColor" aria-hidden="true"><path d="M13 2L3 14h7l-1 8 10-12h-7l1-8z"/></svg>';
		btn.addEventListener( 'click', function ( e ) {
			e.preventDefault();
			if ( openPop ) {
				closePop();
				return;
			}
			buildPop( ctx, btn );
		} );
		return btn;
	}

	function addButton( wrap ) {
		if ( wrap.dataset.cafwDyn ) {
			return;
		}
		if ( wrap.classList.contains( 'cafw-no-dyn' ) ) {
			wrap.dataset.cafwDyn = '1';
			return;
		}
		var html = wrap.classList.contains( 'wpb_el_type_textarea_html' );
		var field = html ? wrap.querySelector( 'textarea' ) : wrap.querySelector( '.wpb_vc_param_value' );
		if ( ! field ) {
			return;
		}
		wrap.dataset.cafwDyn = '1';

		var ctx = { el: field, html: html, id: field.id };
		var btn = makeButton( ctx );

		var ai = wrap.querySelector( '.vc_ui-icon-ai' );
		if ( ai && ai.parentNode ) {
			btn.classList.add( 'cafw-dyn-btn--ai' );
			ai.parentNode.insertBefore( btn, ai );
		} else {
			var holder = field.parentNode;
			if ( ! holder ) {
				return;
			}
			holder.classList.add( 'cafw-dyn-field' );
			holder.appendChild( btn );
		}
	}

	function scan() {
		var nodes = document.querySelectorAll(
			'.wpb_el_type_textfield, .wpb_el_type_textarea, .wpb_el_type_textarea_safe, .wpb_el_type_textarea_html'
		);
		Array.prototype.forEach.call( nodes, addButton );
	}

	var scheduled = false;
	function schedule() {
		if ( scheduled ) {
			return;
		}
		scheduled = true;
		window.requestAnimationFrame( function () {
			scheduled = false;
			scan();
		} );
	}

	function start() {
		scan();
		new MutationObserver( schedule ).observe( document.body, { childList: true, subtree: true } );
	}

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