/**
 * EasySite Visual Editor v1.5 – Divi-style front-end editing
 */
(function ($) {
	'use strict';

	var layout, registry, designFields, postId, dirty = false, activeBlockId = null;
	var linkEdit = { field: null, blockId: null, isRegion: false };
	var currentDevice = 'desktop';
	var regionState = { header_layout: [], footer_layout: {}, header_button_text: '', header_button_link: '', footer_text: '', site_title: '', logo_id: 0 };
	var rteTarget = null;

	function init() {
		if (typeof easysiteVE === 'undefined') return;

		layout = easysiteVE.layout || [];
		registry = easysiteVE.registry || {};
		designFields = easysiteVE.designFields || {};
		postId = easysiteVE.postId;

		regionState.header_layout = easysiteVE.headerLayout || [];
		regionState.footer_layout = easysiteVE.footerLayout || { columns: 3, blocks: [] };
		$.extend(regionState, easysiteVE.regionMods || {});

		layout.forEach(function (b) {
			if (!b.design) b.design = defaultDesign();
		});

		initViewport();
		normalizeBlocks();
		wrapBlocks();
		wrapRegions();
		buildLibrary();
		buildHeaderPanel();
		buildFooterPanel();
		bindEvents();
		applyDevicePreview();
		updateStatus('');
	}

	function defaultDesign() {
		return { padding_top: 'normal', padding_bottom: 'normal', bg_color: '', bg_image: '', text_color: '', border_radius: 'none', tablet: {}, mobile: {} };
	}

	function uid() {
		return 'esb_' + Math.random().toString(36).slice(2, 11);
	}

	function initViewport() {
		if ($('#esb-ve-viewport').length) return;
		$('#site-header, #main, #site-footer').wrapAll('<div id="esb-ve-viewport" class="esb-ve-viewport esb-ve-viewport--desktop"></div>');
	}

	function normalizeBlocks() {
		$('.easysite-pb-block').each(function (i) {
			var $b = $(this);
			var id = $b.data('block-id');
			if (!id) {
				id = layout[i] && layout[i].id ? layout[i].id : uid();
				$b.attr('data-block-id', id);
			}
			if (layout[i] && !layout[i].id) layout[i].id = id;
		});
	}

	function getBlockById(id) {
		return layout.find(function (b) { return b.id === id; });
	}

	function getBlockIndex(id) {
		return layout.findIndex(function (b) { return b.id === id; });
	}

	function markDirty() {
		dirty = true;
		updateStatus(easysiteVE.i18n.unsaved);
		$(document).trigger('esbVEStateChanged');
	}

	function updateStatus(msg) {
		$('#esb-ve-status').text(msg || '');
	}

	function applyDevicePreview() {
		$('#esb-ve-viewport').attr('class', 'esb-ve-viewport esb-ve-viewport--' + currentDevice);
		$('body').removeClass('esb-ve-preview-tablet esb-ve-preview-mobile').addClass(currentDevice !== 'desktop' ? 'esb-ve-preview-' + currentDevice : '');
		applyResponsiveDesign();
	}

	function applyResponsiveDesign() {
		var bp = currentDevice === 'desktop' ? 'desktop' : currentDevice;
		$('.easysite-pb-block[data-esb-design]').each(function () {
			var id = $(this).data('block-id');
			var block = getBlockById(id);
			if (!block) return;
			var style = buildDesignStyle(block, bp);
			$(this).attr('style', style);
		});
	}

	function buildDesignStyle(block, breakpoint) {
		var d = block.design || defaultDesign();
		var spacing = easysiteVE.spacingMap || { none: '0', small: '2rem', normal: '4rem', large: '6rem' };
		var vals = $.extend({}, d);
		if (breakpoint === 'tablet' && d.tablet) vals = $.extend(vals, d.tablet);
		if (breakpoint === 'mobile' && d.mobile) vals = $.extend(vals, d.mobile);
		if (vals.hide && breakpoint !== 'desktop') return 'display:none;';

		var parts = [];
		if (spacing[vals.padding_top]) parts.push('padding-top:' + spacing[vals.padding_top]);
		if (spacing[vals.padding_bottom]) parts.push('padding-bottom:' + spacing[vals.padding_bottom]);
		if (vals.bg_color) parts.push('background-color:' + vals.bg_color);
		if (vals.bg_image) parts.push("background-image:url('" + vals.bg_image + "')", 'background-size:cover', 'background-position:center');
		if (vals.text_color) parts.push('color:' + vals.text_color);
		var radius = { none: '0', small: '8px', medium: '16px', large: '24px' };
		if (vals.border_radius && radius[vals.border_radius] && vals.border_radius !== 'none') {
			parts.push('border-radius:' + radius[vals.border_radius], 'overflow:hidden');
		}
		return parts.join(';') + (parts.length ? ';' : '');
	}

	function wrapRegions() {
		$('.esb-ve-region').each(function () {
			var $r = $(this);
			if ($r.find('> .esb-ve-region-bar').length) return;
			var region = $r.data('esb-region');
			var label = region === 'header' ? easysiteVE.i18n.editHeader : easysiteVE.i18n.editFooter;
			$r.prepend('<div class="esb-ve-region-bar"><span>' + label + '</span><button type="button" class="esb-ve-btn esb-ve-btn--ghost esb-ve-region-edit" data-region="' + region + '">' + label + '</button></div>');
		});
	}

	function wrapBlocks() {
		$('.easysite-pb-page .easysite-pb-block').each(function () {
			var $block = $(this);
			if ($block.children('.esb-ve-block-toolbar').length) return;

			var id = $block.data('block-id');
			var type = $block.data('block-type') || '';
			var label = registry[type] ? registry[type].label : type;

			$block.prepend(
				'<div class="esb-ve-block-toolbar">' +
				'<span class="esb-ve-block-label"><span class="dashicons dashicons-move"></span> ' + label + '</span>' +
				'<div class="esb-ve-block-actions">' +
				'<button type="button" class="esb-ve-icon-btn" data-action="settings" title="' + easysiteVE.i18n.settings + '"><span class="dashicons dashicons-admin-generic"></span></button>' +
				'<button type="button" class="esb-ve-icon-btn" data-action="up"><span class="dashicons dashicons-arrow-up-alt2"></span></button>' +
				'<button type="button" class="esb-ve-icon-btn" data-action="down"><span class="dashicons dashicons-arrow-down-alt2"></span></button>' +
				'<button type="button" class="esb-ve-icon-btn" data-action="duplicate"><span class="dashicons dashicons-admin-page"></span></button>' +
				'<button type="button" class="esb-ve-icon-btn esb-ve-icon-btn--danger" data-action="remove"><span class="dashicons dashicons-trash"></span></button>' +
				'</div></div>'
			);

			if ($block.hasClass('easysite-pb-hero')) {
				$block.find('section').first().append(
					'<button type="button" class="esb-ve-change-bg" data-esb-field="bg_image" data-esb-type="bg-image">' +
					'<span class="dashicons dashicons-format-image"></span> ' + easysiteVE.i18n.changeBg + '</button>'
				);
			}
		});

		var $page = $('.easysite-pb-page');
		if ($page.length && !$page.hasClass('ui-sortable')) {
			$page.sortable({
				items: '> .easysite-pb-block',
				handle: '.esb-ve-block-label',
				placeholder: 'esb-ve-sort-placeholder',
				tolerance: 'pointer',
				update: function () { syncOrderFromDom(); markDirty(); }
			});
		}
		$(document).trigger('esbVEBlocksWrapped');
	}

	function syncOrderFromDom() {
		var newLayout = [];
		$('.easysite-pb-page .easysite-pb-block').each(function () {
			var block = getBlockById($(this).data('block-id'));
			if (block) newLayout.push(block);
		});
		layout = newLayout;
	}

	function bindEvents() {
		$('#esb-ve-save').on('click', saveAll);
		$('#esb-ve-add-section').on('click', function () { $('#esb-ve-library').removeAttr('hidden'); });
		$('#esb-ve-edit-header').on('click', function () { $('#esb-ve-header-panel').removeAttr('hidden'); });
		$('#esb-ve-edit-footer').on('click', function () { $('#esb-ve-footer-panel').removeAttr('hidden'); });

		$('.esb-ve-device').on('click', function () {
			currentDevice = $(this).data('device');
			$('.esb-ve-device').removeClass('is-active');
			$(this).addClass('is-active');
			applyDevicePreview();
		});

		$('[data-close-panel]').on('click', function () { $(this).closest('.esb-ve-panel').attr('hidden', true); });

		$('.esb-ve-tab').on('click', function () {
			var tab = $(this).data('tab');
			$('.esb-ve-tab').removeClass('is-active');
			$(this).addClass('is-active');
			$('.esb-ve-tab-panel').attr('hidden', true).removeClass('is-active');
			$('#esb-ve-settings-' + tab).removeAttr('hidden').addClass('is-active');
		});

		$(document).on('click', '.esb-ve-library-item', function () {
			if ($(this).hasClass('esb-ve-preset-item') || $(this).hasClass('esb-ve-global-item')) return;
			addSection($(this).data('type'));
			$('#esb-ve-library').attr('hidden', true);
		});

		$(document).on('click', '.esb-ve-preset-item', function () {
			var preset = (easysiteVE.sectionPresets || {})[$(this).data('preset')];
			if (!preset || !preset.block || !window.esbVEApi) return;
			window.esbVEApi.insertBlock(preset.block);
			$('#esb-ve-library').attr('hidden', true);
		});

		$(document).on('click', '.esb-ve-block-toolbar [data-action]', function (e) {
			e.preventDefault();
			var action = $(this).data('action');
			var $block = $(this).closest('.easysite-pb-block');
			var id = $block.data('block-id');
			if (action === 'remove' && confirm(easysiteVE.i18n.remove + '?')) removeBlock(id, $block);
			else if (action === 'duplicate') duplicateBlock(id, $block);
			else if (action === 'up') moveBlock($block, -1);
			else if (action === 'down') moveBlock($block, 1);
			else if (action === 'settings') openSettings(id);
		});

		$(document).on('input blur', '[data-esb-type="text"]', function () {
			syncTextField($(this));
		});

		$(document).on('input blur', '[data-esb-type="richtext"]', function () {
			syncRichField($(this));
		});

		$(document).on('focus', '[data-esb-type="text"], [data-esb-type="richtext"]', function () {
			var $el = $(this);
			if ($el.hasClass('esb-placeholder')) $el.empty().removeClass('esb-placeholder');
			if ($el.data('esb-type') === 'richtext') rteTarget = $el[0];
		});

		$(document).on('mouseup keyup', '[data-esb-type="richtext"]', positionRteToolbar);

		$(document).on('click', '#esb-ve-rte-toolbar button', function (e) {
			e.preventDefault();
			var cmd = $(this).data('cmd');
			var val = $(this).data('value');
			if (!rteTarget) return;
			rteTarget.focus();
			if (cmd === 'createLink') {
				var url = prompt(easysiteVE.i18n.linkUrl, 'https://');
				if (url) document.execCommand(cmd, false, url);
			} else if (cmd === 'formatBlock') {
				document.execCommand(cmd, false, '<' + val + '>');
			} else {
				document.execCommand(cmd, false, null);
			}
			$(rteTarget).trigger('input');
		});

		$(document).on('click', function (e) {
			if (!$(e.target).closest('#esb-ve-rte-toolbar, [data-esb-type="richtext"]').length) {
				$('#esb-ve-rte-toolbar').attr('hidden', true);
			}
		});

		$(document).on('click', '.esb-editable-image, .esb-ve-change-bg, [data-esb-type="image"]', function (e) {
			e.preventDefault();
			e.stopPropagation();
			var $t = $(this);
			var field = $t.data('esb-field') || $t.closest('[data-esb-field]').data('esb-field') || 'image';
			pickImage($t.closest('.easysite-pb-block').data('block-id'), field, $t);
		});

		$(document).on('click', '.esb-ve-change-logo', function (e) {
			e.preventDefault();
			pickLogo();
		});

		$(document).on('contextmenu', '.esb-editable-button', function (e) { e.preventDefault(); openLinkModal($(this)); });
		$(document).on('click', '.esb-editable-button', function (e) { if (e.shiftKey) { e.preventDefault(); openLinkModal($(this)); } });

		$('#esb-ve-link-save').on('click', applyLink);
		$('[data-close-modal]').on('click', function () { $('#esb-ve-link-modal').attr('hidden', true); });

		$('#esb-ve-exit').on('click', function (e) {
			if (dirty && !confirm(easysiteVE.i18n.unsaved + '?')) e.preventDefault();
		});

		$(document).on('change', '#esb-ve-settings-content input, #esb-ve-settings-content select', function () {
			if (!activeBlockId) return;
			var block = getBlockById(activeBlockId);
			block.fields[$(this).data('field')] = $(this).val();
			markDirty();
			rerenderBlock(activeBlockId);
		});

		$(document).on('change', '#esb-ve-settings-design input, #esb-ve-settings-design select', function () {
			if (!activeBlockId) return;
			var block = getBlockById(activeBlockId);
			if (!block.design) block.design = defaultDesign();
			block.design[$(this).data('design')] = $(this).val();
			markDirty();
			applyBlockDesign(activeBlockId);
		});

		$(document).on('click', '#esb-ve-settings-design .esb-ve-pick-image', function () {
			pickImage(activeBlockId, $(this).data('design'), $(this), true);
		});

		$(document).on('click', '#esb-ve-settings-content .esb-ve-pick-image', function () {
			pickImage(activeBlockId, $(this).data('field'), $(this), false);
		});

		$(document).on('change', '#esb-ve-responsive-fields input, #esb-ve-responsive-fields select', function () {
			if (!activeBlockId) return;
			var block = getBlockById(activeBlockId);
			var bp = currentDevice === 'mobile' ? 'mobile' : 'tablet';
			if (!block.design) block.design = defaultDesign();
			if (!block.design[bp]) block.design[bp] = {};
			var key = $(this).data('responsive');
			if ($(this).attr('type') === 'checkbox') block.design[bp][key] = $(this).is(':checked');
			else block.design[bp][key] = $(this).val();
			markDirty();
			applyBlockDesign(activeBlockId);
		});

		$(document).on('input blur', '[data-esb-region-field]', function () {
			var key = $(this).data('esb-region-field');
			if (key === 'site_title') regionState.site_title = $(this).text().trim();
			else if (key === 'header_button_text') regionState.header_button_text = $(this).text().trim();
			else if (key === 'footer_text') regionState.footer_text = $(this).text().trim();
			markDirty();
		});

		$(document).on('change', '#esb-ve-header-fields input, #esb-ve-header-fields select', function () {
			if ($(this).attr('name') === 'header_button_link') regionState.header_button_link = $(this).val();
			markDirty();
		});

		$(document).on('change', '#esb-ve-footer-fields select', function () {
			regionState.footer_layout.columns = parseInt($(this).val(), 10);
			markDirty();
		});
	}

	function positionRteToolbar() {
		var sel = window.getSelection();
		if (!sel || sel.isCollapsed || !$(sel.anchorNode).closest('[data-esb-type="richtext"]').length) {
			return;
		}
		var range = sel.getRangeAt(0);
		var rect = range.getBoundingClientRect();
		$('#esb-ve-rte-toolbar').css({ top: rect.top + window.scrollY - 48, left: rect.left + window.scrollX }).removeAttr('hidden');
	}

	function syncTextField($el) {
		var field = $el.data('esb-field');
		if ($el.data('esb-region-field')) {
			regionState[$el.data('esb-region-field')] = $.trim($el.text());
			markDirty();
			return;
		}
		var block = getBlockById($el.closest('.easysite-pb-block').data('block-id'));
		if (block) { block.fields[field] = $.trim($el.text()); markDirty(); }
	}

	function syncRichField($el) {
		var block = getBlockById($el.closest('.easysite-pb-block').data('block-id'));
		if (block) { block.fields[$el.data('esb-field')] = $el.html(); markDirty(); }
	}

	function applyRegionsToDom() {
		$('[data-esb-region-field]').each(function () {
			var key = $(this).data('esb-region-field');
			if (regionState[key] === undefined) return;
			if ($(this).is('button, a.easysite-btn')) $(this).text(regionState[key]);
			else $(this).text(regionState[key]);
		});
		if (regionState.header_button_link) {
			var href = regionState.header_button_link.indexOf('http') === 0 ? regionState.header_button_link : (window.location.origin + regionState.header_button_link);
			$('[data-esb-link-field="header_button_link"]').attr('href', href);
		}
	}

	function rerenderAllBlocks(cb) {
		var $page = $('.easysite-pb-page');
		if (!$page.length) {
			if (cb) cb();
			return;
		}
		$page.empty();
		if (!layout.length) {
			wrapBlocks();
			if (cb) cb();
			return;
		}
		var remaining = layout.length;
		layout.forEach(function (block) {
			$.post(easysiteVE.ajaxUrl, { action: 'easysite_ve_render_block', nonce: easysiteVE.nonce, post_id: postId, block: JSON.stringify(block) })
				.done(function (res) {
					if (res.success) $page.append($(res.data.html));
				})
				.always(function () {
					remaining--;
					if (remaining <= 0) {
						wrapBlocks();
						layout.forEach(function (b) { applyBlockDesign(b.id); });
						applyRegionsToDom();
						if (cb) cb();
					}
				});
		});
	}

	function applySnapshot(snapshot, cb, silent) {
		layout = JSON.parse(JSON.stringify(snapshot.layout || []));
		$.extend(regionState, snapshot.regions || {});
		rerenderAllBlocks(function () {
			if (!silent) markDirty();
			if (cb) cb();
		});
	}

	function afterBlockInsert() {
		wrapBlocks();
		markDirty();
	}

	function applyBlockDesign(id) {
		var block = getBlockById(id);
		var $el = $('.easysite-pb-block[data-block-id="' + id + '"]');
		if (block && $el.length) $el.attr('style', buildDesignStyle(block, currentDevice === 'desktop' ? 'desktop' : currentDevice));
	}

	function buildLibrary() {
		var $grid = $('#esb-ve-library-grid').empty();
		if (easysiteVE.sectionPresets && Object.keys(easysiteVE.sectionPresets).length) {
			$grid.append('<p class="esb-ve-library-heading">' + (easysiteVE.i18n.presets || 'Quick presets') + '</p>');
			$.each(easysiteVE.sectionPresets, function (key, preset) {
				$grid.append('<button type="button" class="esb-ve-library-item esb-ve-preset-item" data-preset="' + key + '"><span class="dashicons ' + (preset.icon || 'dashicons-layout') + '"></span><strong>' + preset.label + '</strong><span>' + (preset.description || '') + '</span></button>');
			});
			$grid.append('<p class="esb-ve-library-heading">' + (easysiteVE.i18n.allSections || 'All sections') + '</p>');
		}
		$.each(registry, function (type, def) {
			$grid.append('<button type="button" class="esb-ve-library-item" data-type="' + type + '"><span class="dashicons ' + def.icon + '"></span><strong>' + def.label + '</strong><span>' + def.description + '</span></button>');
		});
	}

	function buildHeaderPanel() {
		var $f = $('#esb-ve-header-fields').empty();
		var $list = $('<ul class="esb-ve-sort-list" id="esb-ve-header-sort"></ul>');
		$.each(regionState.header_layout, function (_, key) {
			var label = (easysiteVE.headerElements || {})[key] || key;
			$list.append('<li data-element="' + key + '"><span class="dashicons dashicons-move"></span> ' + label + '</li>');
		});
		$f.append('<p><strong>' + easysiteVE.i18n.headerLayout + '</strong></p>').append($list);
		$f.append('<p><label>' + easysiteVE.i18n.linkUrl + '<input type="text" class="esb-ve-input" name="header_button_link" value="' + (regionState.header_button_link || '') + '" /></label></p>');
		$list.sortable({ update: function () {
			regionState.header_layout = [];
			$list.find('li').each(function () { regionState.header_layout.push($(this).data('element')); });
			markDirty();
		}});
	}

	function buildFooterPanel() {
		var $f = $('#esb-ve-footer-fields').empty();
		$f.append('<label>' + easysiteVE.i18n.footerLayout + ' – ' + easysiteVE.i18n.columns + '<select class="esb-ve-input"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select></label>');
		$f.find('select').val(regionState.footer_layout.columns || 3);
	}

	function addSection(type) {
		if (!registry[type]) return;
		var block = { id: uid(), type: type, fields: {}, design: defaultDesign() };
		$.each(registry[type].fields, function (k) { block.fields[k] = ''; });
		layout.push(block);
		$.post(easysiteVE.ajaxUrl, { action: 'easysite_ve_render_block', nonce: easysiteVE.nonce, post_id: postId, block: JSON.stringify(block) })
			.done(function (res) {
				if (res.success) {
					$('.easysite-pb-page').append($(res.data.html));
					afterBlockInsert();
				}
			});
	}

	function removeBlock(id, $block) { layout = layout.filter(function (b) { return b.id !== id; }); $block.remove(); markDirty(); }

	function duplicateBlock(id, $block) {
		var copy = JSON.parse(JSON.stringify(getBlockById(id)));
		copy.id = uid();
		layout.splice(getBlockIndex(id) + 1, 0, copy);
		$.post(easysiteVE.ajaxUrl, { action: 'easysite_ve_render_block', nonce: easysiteVE.nonce, post_id: postId, block: JSON.stringify(copy) })
			.done(function (res) { if (res.success) { $block.after(res.data.html); afterBlockInsert(); } });
	}

	function moveBlock($block, dir) {
		var $s = dir < 0 ? $block.prev('.easysite-pb-block') : $block.next('.easysite-pb-block');
		if (!$s.length) return;
		dir < 0 ? $block.insertBefore($s) : $block.insertAfter($s);
		syncOrderFromDom();
		markDirty();
	}

	function renderDesignFields($container, block, prefix) {
		$container.empty();
		$.each(designFields, function (key, field) {
			var val = prefix ? (block.design[prefix] || {})[key] || '' : (block.design || {})[key] || '';
			var $row = $('<div class="esb-ve-field-row"></div>');
			$row.append('<label>' + field.label + '</label>');
			var dataAttr = prefix ? 'data-responsive="' + key + '"' : 'data-design="' + key + '"';
			if (field.type === 'select') {
				var $sel = $('<select ' + dataAttr + '></select>');
				$.each(field.options, function (v, l) { $sel.append('<option value="' + v + '"' + (val === v ? ' selected' : '') + '>' + l + '</option>'); });
				$row.append($sel);
			} else if (field.type === 'color') {
				$row.append('<input type="color" ' + dataAttr + ' value="' + (val || '#ffffff') + '" />');
			} else if (field.type === 'image') {
				$row.append('<button type="button" class="esb-ve-btn esb-ve-btn--ghost esb-ve-pick-image" data-design="' + key + '">' + easysiteVE.i18n.changeImage + '</button><input type="hidden" ' + dataAttr + ' value="' + val + '" />');
			}
			$container.append($row);
		});
		if (prefix) {
			var hide = (block.design[prefix] || {}).hide;
			$container.append('<label><input type="checkbox" data-responsive="hide" ' + (hide ? 'checked' : '') + ' /> ' + easysiteVE.i18n.hideOnDevice + '</label>');
		}
	}

	function openSettings(id) {
		activeBlockId = id;
		var block = getBlockById(id);
		if (!block || !registry[block.type]) return;
		if (!block.design) block.design = defaultDesign();

		var def = registry[block.type];
		$('#esb-ve-settings-title').text(def.label);

		var $content = $('#esb-ve-settings-content').empty();
		$.each(def.fields, function (key, field) {
			if (field.type === 'text' || field.type === 'textarea') return;
			var val = block.fields[key] || '';
			var $row = $('<div class="esb-ve-field-row"><label>' + field.label + '</label></div>');
			if (field.type === 'select') {
				var $sel = $('<select data-field="' + key + '"></select>');
				$.each(field.options, function (v, l) { $sel.append('<option value="' + v + '"' + (val === v ? ' selected' : '') + '>' + l + '</option>'); });
				$row.append($sel);
			} else if (field.type === 'image') {
				$row.append('<button type="button" class="esb-ve-btn esb-ve-pick-image" data-field="' + key + '">' + easysiteVE.i18n.changeImage + '</button>');
			} else {
				$row.append('<input type="text" class="esb-ve-input" data-field="' + key + '" value="' + val + '" />');
			}
			$content.append($row);
		});

		renderDesignFields($('#esb-ve-settings-design'), block, '');
		var bp = currentDevice === 'mobile' ? 'mobile' : 'tablet';
		renderDesignFields($('#esb-ve-responsive-fields'), block, bp);

		$('#esb-ve-settings').removeAttr('hidden');
		$('.esb-ve-tab').first().click();
	}

	function pickImage(blockId, field, $trigger, isDesign) {
		var block = getBlockById(blockId);
		if (!block) return;
		var frame = wp.media({ title: easysiteVE.i18n.changeImage, button: { text: easysiteVE.i18n.changeImage }, multiple: false });
		frame.on('select', function () {
			var url = frame.state().get('selection').first().toJSON().url;
			if (isDesign) {
				if (!block.design) block.design = defaultDesign();
				block.design[field] = url;
				applyBlockDesign(blockId);
			} else {
				block.fields[field] = url;
				if (field === 'bg_image') $trigger.closest('.easysite-pb-block').find('.easysite-pb-hero').css('background-image', "url('" + url + "')");
				else {
					var $imgWrap = $trigger.closest('.esb-editable-image');
					if ($imgWrap.length) $imgWrap.find('img').attr('src', url);
					else $trigger.closest('.easysite-pb-block').find('[data-esb-field="' + field + '"] img').attr('src', url);
				}
			}
			markDirty();
		});
		frame.open();
	}

	function pickLogo() {
		var frame = wp.media({ title: easysiteVE.i18n.changeLogo, button: { text: easysiteVE.i18n.changeLogo }, multiple: false });
		frame.on('select', function () {
			var att = frame.state().get('selection').first().toJSON();
			regionState.logo_id = att.id;
			var $wrap = $('.esb-ve-logo-wrap');
			if ($wrap.find('img.custom-logo').length) $wrap.find('img.custom-logo').attr('src', att.url);
			else $wrap.find('.easysite-site-title').replaceWith('<a href="/" class="custom-logo-link"><img src="' + att.url + '" class="custom-logo" alt="" /></a>');
			markDirty();
		});
		frame.open();
	}

	function rerenderBlock(id) {
		var block = getBlockById(id);
		$.post(easysiteVE.ajaxUrl, { action: 'easysite_ve_render_block', nonce: easysiteVE.nonce, post_id: postId, block: JSON.stringify(block) })
			.done(function (res) {
				if (res.success) {
					$('.easysite-pb-block[data-block-id="' + id + '"]').replaceWith(res.data.html);
					wrapBlocks();
					applyBlockDesign(id);
				}
			});
	}

	function openLinkModal($btn) {
		linkEdit.isRegion = !!$btn.data('esb-region-field');
		if (linkEdit.isRegion) {
			linkEdit.field = $btn.data('esb-link-field');
			$('#esb-ve-link-input').val(regionState[linkEdit.field] || '');
		} else {
			linkEdit.blockId = $btn.closest('.easysite-pb-block').data('block-id');
			linkEdit.field = $btn.data('esb-link-field') || 'button_url';
			$('#esb-ve-link-input').val((getBlockById(linkEdit.blockId) || {}).fields[linkEdit.field] || '');
		}
		$('#esb-ve-link-modal').removeAttr('hidden');
	}

	function applyLink() {
		var url = $('#esb-ve-link-input').val();
		if (linkEdit.isRegion) {
			regionState[linkEdit.field] = url;
			$('[data-esb-link-field="' + linkEdit.field + '"]').attr('href', url.indexOf('http') === 0 ? url : (window.location.origin + url));
		} else {
			var block = getBlockById(linkEdit.blockId);
			if (block) {
				block.fields[linkEdit.field] = url;
				$('.easysite-pb-block[data-block-id="' + linkEdit.blockId + '"]').find('[data-esb-link-field="' + linkEdit.field + '"]').attr('href', url.indexOf('http') === 0 ? url : (window.location.origin + url));
			}
		}
		$('#esb-ve-link-modal').attr('hidden', true);
		markDirty();
	}

	function syncAllFromDom() {
		syncOrderFromDom();
		$('[data-esb-type="text"]').each(function () { syncTextField($(this)); });
		$('[data-esb-type="richtext"]').each(function () { syncRichField($(this)); });
	}

	function saveAll() {
		syncAllFromDom();
		var $btn = $('#esb-ve-save').prop('disabled', true);
		$.post(easysiteVE.ajaxUrl, {
			action: 'easysite_ve_save_layout',
			nonce: easysiteVE.nonce,
			post_id: postId,
			layout: JSON.stringify(layout),
			regions: JSON.stringify(regionState)
		}).done(function (res) {
			if (res.success) { dirty = false; updateStatus(easysiteVE.i18n.saved); setTimeout(function () { updateStatus(''); }, 2500); }
			else updateStatus(easysiteVE.i18n.error);
		}).fail(function () { updateStatus(easysiteVE.i18n.error); })
			.always(function () { $btn.prop('disabled', false); });
	}

	window.esbVEApi = {
		getLayout: function () { return layout; },
		setLayout: function (l) { layout = l; },
		getRegions: function () { return regionState; },
		setRegions: function (r) { $.extend(regionState, r); },
		markDirty: markDirty,
		applyBlockDesign: applyBlockDesign,
		applySnapshot: applySnapshot,
		rerenderAllBlocks: rerenderAllBlocks,
		postId: function () { return postId; },
		insertBlock: function (block) {
			if (!block) return;
			block = JSON.parse(JSON.stringify(block));
			block.id = uid();
			if (!block.design) block.design = defaultDesign();
			layout.push(block);
			$.post(easysiteVE.ajaxUrl, { action: 'easysite_ve_render_block', nonce: easysiteVE.nonce, post_id: postId, block: JSON.stringify(block) })
				.done(function (res) {
					if (res.success) {
						$('.easysite-pb-page').append($(res.data.html));
						afterBlockInsert();
					}
				});
		},
		saveLayout: function (newLayout, regions, cb) {
			var payload = {
				action: 'easysite_ve_save_layout',
				nonce: easysiteVE.nonce,
				post_id: postId,
				layout: JSON.stringify(newLayout)
			};
			if (regions) payload.regions = JSON.stringify(regions);
			$.post(easysiteVE.ajaxUrl, payload).done(function (res) { if (cb) cb(res); });
		}
	};

	$(init);
})(jQuery);
