'use strict';

document.addEventListener('DOMContentLoaded', function () {
	initSubmissionInboxGrapesJS();
});

function initSubmissionInboxGrapesJS() {
	var container = document.getElementById('subin-grapesjs-editor');

	if (!container || typeof window.grapesjs === 'undefined') {
		return;
	}

	if (container.getAttribute('data-subin-grapesjs-ready') === '1') {
		return;
	}

	container.setAttribute('data-subin-grapesjs-ready', '1');

	var namespace = window.SubmissionInbox = window.SubmissionInbox || {};
	namespace.designStudio = namespace.designStudio || {};

	namespace.designStudio.editor = window.grapesjs.init({
		container: container,
		height: '760px',
		storageManager: false,
		telemetry: false,
		plugins: [registerSubmissionInboxComponents],
		selectorManager: {
			componentFirst: true,
		},
		blockManager: {
			blocks: buildSubmissionInboxBlocks(),
		},
		styleManager: buildSubmissionInboxStyleManager(),
	});

	window.SUBINGrapesJSEditor = namespace.designStudio.editor;

	removeSubmissionInboxUnusedPanelButtons(window.SUBINGrapesJSEditor);
	loadExistingSubmissionInboxForm(window.SUBINGrapesJSEditor);
	initSubmissionInboxPreviewStateSwitcher(window.SUBINGrapesJSEditor);
	initSubmissionInboxInteractivePreviewMode(window.SUBINGrapesJSEditor);
	initSubmissionInboxHtmlEditorModal(window.SUBINGrapesJSEditor);
	initSubmissionInboxUnifiedInspector(window.SUBINGrapesJSEditor);
	initSubmissionInboxStyleManagerSelection(window.SUBINGrapesJSEditor);
	initSubmissionInboxFlowLayout(window.SUBINGrapesJSEditor);
	initGrapesJSSave(window.SUBINGrapesJSEditor);
}

function removeSubmissionInboxUnusedPanelButtons(editor) {
	var panels = editor && editor.Panels;

	if (!panels || !panels.removeButton) {
		return;
	}

	panels.removeButton('options', 'sw-visibility');
	panels.removeButton('options', 'export-template');
}

function initSubmissionInboxInteractivePreviewMode(editor) {
	if (!editor || !editor.on) {
		return;
	}

	bindSubmissionInboxPreviewPanelFallback(editor);
	['run:core:preview', 'run:preview'].forEach(function (eventName) {
		editor.on(eventName, function () {
			scheduleSubmissionInboxInteractivePreviewMode(editor, true);
		});
	});
	['stop:core:preview', 'stop:preview'].forEach(function (eventName) {
		editor.on(eventName, function () {
			scheduleSubmissionInboxInteractivePreviewMode(editor, false);
		});
	});
	editor.on('canvas:frame:load', function () {
		if (editor.__subinInteractivePreviewActive) {
			setSubmissionInboxInteractivePreviewMode(editor, true);
		}
	});
}

function bindSubmissionInboxPreviewPanelFallback(editor) {
	var container = editor && editor.getContainer ? editor.getContainer() : document.getElementById('subin-grapesjs-editor');

	if (!container || container.__subinPreviewPanelFallbackBound) {
		return;
	}

	container.__subinPreviewPanelFallbackBound = true;
	container.addEventListener('click', function (event) {
		var button = event.target && event.target.closest ? event.target.closest('.gjs-pn-btn') : null;
		var command;
		var title;

		if (!button) {
			return;
		}

		command = button.getAttribute('data-command') || button.getAttribute('data-id') || '';
		title = String(button.getAttribute('title') || '').toLowerCase();

		if (command !== 'preview' && command !== 'core:preview' && title !== 'preview') {
			return;
		}

		window.setTimeout(function () {
			var active = isSubmissionInboxPreviewButtonActive(button);
			scheduleSubmissionInboxInteractivePreviewMode(editor, active === null ? !editor.__subinInteractivePreviewActive : active);
		}, 0);
	}, true);
}

function isSubmissionInboxPreviewButtonActive(button) {
	if (!button) {
		return null;
	}

	if (
		button.classList.contains('gjs-pn-active') ||
		button.classList.contains('gjs-four-color') ||
		button.getAttribute('aria-pressed') === 'true'
	) {
		return true;
	}

	if (
		button.classList.contains('gjs-pn-inactive') ||
		button.getAttribute('aria-pressed') === 'false'
	) {
		return false;
	}

	return null;
}

function scheduleSubmissionInboxInteractivePreviewMode(editor, active) {
	setSubmissionInboxInteractivePreviewMode(editor, active);
	window.setTimeout(function () {
		setSubmissionInboxInteractivePreviewMode(editor, active);
	}, 50);
	window.setTimeout(function () {
		setSubmissionInboxInteractivePreviewMode(editor, active);
	}, 200);
}

function setSubmissionInboxInteractivePreviewMode(editor, active) {
	var wrapperEls = getSubmissionInboxCanvasFormPreviewElements(editor);

	editor.__subinInteractivePreviewActive = !!active;

	if (!wrapperEls.length) {
		return;
	}

	wrapperEls.forEach(function (wrapperEl) {
		wrapperEl.classList.toggle('subin-gjs-runtime-preview', !!active);
		toggleSubmissionInboxPreviewControls(wrapperEl, !!active);
		bindSubmissionInboxPreviewSubmitGuard(wrapperEl);
	});
}

function getSubmissionInboxCanvasFormPreviewElements(editor) {
	var wrapper = editor && editor.getWrapper ? editor.getWrapper() : null;
	var wrapperEl = wrapper && wrapper.view ? wrapper.view.el : null;
	var body = editor && editor.Canvas && editor.Canvas.getBody ? editor.Canvas.getBody() : null;
	var elements = [];

	if (wrapperEl) {
		elements.push(wrapperEl);
	}

	if (body && body.querySelectorAll) {
		body.querySelectorAll('.subin-gjs-form-preview').forEach(function (element) {
			if (elements.indexOf(element) === -1) {
				elements.push(element);
			}
		});
	}

	return elements;
}

function toggleSubmissionInboxPreviewControls(wrapperEl, active) {
	wrapperEl.querySelectorAll('[data-subin-preview-control]').forEach(function (control) {
		if (active) {
			bindSubmissionInboxPreviewControlGuard(control);
			if (control.hasAttribute('disabled')) {
				control.setAttribute('data-subin-preview-disabled', '1');
				control.removeAttribute('disabled');
			}
			if (control.hasAttribute('readonly')) {
				control.setAttribute('data-subin-preview-readonly', '1');
				control.removeAttribute('readonly');
			}
		} else {
			if (control.getAttribute('data-subin-preview-disabled') === '1') {
				control.setAttribute('disabled', 'disabled');
				control.removeAttribute('data-subin-preview-disabled');
			}
			if (control.getAttribute('data-subin-preview-readonly') === '1') {
				control.setAttribute('readonly', 'readonly');
				control.removeAttribute('data-subin-preview-readonly');
			}
		}
	});
	if (active) {
		wrapperEl.querySelectorAll('.subin-choice-row,.subin-checkbox-field').forEach(function (label) {
			bindSubmissionInboxPreviewControlGuard(label);
		});
	}
}

function bindSubmissionInboxPreviewControlGuard(control) {
	if (!control || control.__subinPreviewControlGuardBound) {
		return;
	}

	control.__subinPreviewControlGuardBound = true;
	[
		'pointerdown',
		'mousedown',
		'mouseup',
		'click',
		'dblclick',
		'focus',
		'focusin',
		'keydown',
		'keyup',
		'input',
		'change',
	].forEach(function (eventName) {
		control.addEventListener(eventName, function (event) {
			if (isSubmissionInboxRuntimePreviewControl(control)) {
				event.stopPropagation();
			}
		});
	});
}

function isSubmissionInboxRuntimePreviewControl(control) {
	var preview = control && control.closest ? control.closest('.subin-gjs-form-preview') : null;
	return !!(preview && preview.classList.contains('subin-gjs-runtime-preview'));
}

function bindSubmissionInboxPreviewSubmitGuard(wrapperEl) {
	if (!wrapperEl || wrapperEl.__subinPreviewSubmitGuardBound) {
		return;
	}

	wrapperEl.__subinPreviewSubmitGuardBound = true;
	wrapperEl.addEventListener('submit', function (event) {
		event.preventDefault();
		event.stopPropagation();
	}, true);
	wrapperEl.addEventListener('click', function (event) {
		var button = event.target && event.target.closest ? event.target.closest('.subin-submit-button') : null;
		if (!button) {
			return;
		}
		event.preventDefault();
		event.stopPropagation();
	}, true);
}

function initSubmissionInboxHtmlEditorModal(editor) {
	var modal = document.querySelector('[data-subin-gjs-html-modal]');

	if (!modal || modal.__subinHtmlModalBound) {
		return;
	}

	modal.__subinHtmlModalBound = true;
	modal.addEventListener('click', function (event) {
		if (event.target && event.target.closest && event.target.closest('[data-subin-gjs-html-close]')) {
			closeSubmissionInboxHtmlEditorModal();
			return;
		}

		if (event.target && event.target.closest && event.target.closest('[data-subin-gjs-html-apply]')) {
			applySubmissionInboxHtmlEditorModal(editor);
		}
	});

	document.addEventListener('keydown', function (event) {
		if (event.key === 'Escape' && !modal.hidden) {
			closeSubmissionInboxHtmlEditorModal();
		}
	});
}

function htmlTraitTextarea(elInput) {
	if (!elInput) {
		return null;
	}

	if (elInput.matches && elInput.matches('textarea')) {
		return elInput;
	}

	return elInput.querySelector ? elInput.querySelector('textarea.subin-gjs-html-trait') : null;
}

function openSubmissionInboxHtmlEditorModal(component, textarea, attributeName) {
	var modal = document.querySelector('[data-subin-gjs-html-modal]');
	var value = textarea ? textarea.value : '';

	if (!modal) {
		return;
	}

	modal.__subinHtmlComponent = component;
	modal.__subinHtmlTextarea = textarea;
	modal.__subinHtmlAttributeName = attributeName || 'data-subin-html-content';
	setSubmissionInboxWpEditorContent(value);
	modal.hidden = false;
	document.body.classList.add('subin-gjs-html-modal-open');
	window.setTimeout(function () {
		focusSubmissionInboxWpEditor();
	}, 50);
}

function closeSubmissionInboxHtmlEditorModal() {
	var modal = document.querySelector('[data-subin-gjs-html-modal]');

	if (!modal) {
		return;
	}

	modal.hidden = true;
	modal.__subinHtmlComponent = null;
	modal.__subinHtmlTextarea = null;
	modal.__subinHtmlAttributeName = '';
	document.body.classList.remove('subin-gjs-html-modal-open');
}

function applySubmissionInboxHtmlEditorModal(editor) {
	var modal = document.querySelector('[data-subin-gjs-html-modal]');
	var component = modal && modal.__subinHtmlComponent;
	var textarea = modal && modal.__subinHtmlTextarea;
	var attributeName = modal && modal.__subinHtmlAttributeName ? modal.__subinHtmlAttributeName : 'data-subin-html-content';
	var value = getSubmissionInboxWpEditorContent();
	var next = {};

	if (!modal || !component || !component.addAttributes) {
		closeSubmissionInboxHtmlEditorModal();
		return;
	}

	next[attributeName] = value;
	component.addAttributes(next);
	if (textarea) {
		textarea.value = value;
	}
	updateContentComponentPreview(component);
	if (editor && editor.select) {
		editor.select(component);
	}
	closeSubmissionInboxHtmlEditorModal();
}

function setSubmissionInboxWpEditorContent(value) {
	var editorId = 'subin_gjs_html_editor';
	var textarea = document.getElementById(editorId);
	var editor = window.tinymce && window.tinymce.get ? window.tinymce.get(editorId) : null;

	if (textarea) {
		textarea.value = value || '';
	}
	if (editor && !editor.isHidden()) {
		editor.setContent(value || '');
	}
}

function getSubmissionInboxWpEditorContent() {
	var editorId = 'subin_gjs_html_editor';
	var editor = window.tinymce && window.tinymce.get ? window.tinymce.get(editorId) : null;
	var textarea = document.getElementById(editorId);

	if (editor && !editor.isHidden()) {
		editor.save();
		return editor.getContent();
	}

	return textarea ? textarea.value : '';
}

function focusSubmissionInboxWpEditor() {
	var editorId = 'subin_gjs_html_editor';
	var editor = window.tinymce && window.tinymce.get ? window.tinymce.get(editorId) : null;
	var textarea = document.getElementById(editorId);

	if (editor && !editor.isHidden()) {
		editor.focus();
		return;
	}

	if (textarea && textarea.focus) {
		textarea.focus();
	}
}

function initSubmissionInboxPreviewStateSwitcher(editor) {
	var shell = document.querySelector('.subin-design-studio--grapesjs-shell');
	var buttons = shell ? shell.querySelectorAll('[data-subin-gjs-preview-state]') : [];

	if (!editor || !buttons.length) {
		return;
	}

	editor.__subinPreviewState = editor.__subinPreviewState || 'normal';

	buttons.forEach(function (button) {
		button.addEventListener('click', function () {
			var state = button.getAttribute('data-subin-gjs-preview-state') || 'normal';
			setGrapesJSPreviewState(editor, state, buttons);
		});
	});

	[
		'component:add',
		'component:remove',
		'component:update',
		'component:selected',
		'canvas:frame:load',
		'load',
	].forEach(function (eventName) {
		editor.on(eventName, function () {
			scheduleGrapesJSPreviewStateRefresh(editor);
		});
	});

	setGrapesJSPreviewState(editor, editor.__subinPreviewState, buttons);
}

function setGrapesJSPreviewState(editor, state, buttons) {
	var normalizedState = ['normal', 'error', 'success'].indexOf(state) !== -1 ? state : 'normal';

	editor.__subinPreviewState = normalizedState;
	updateGrapesJSPreviewStateButtons(buttons, normalizedState);
	applyGrapesJSPreviewState(editor, normalizedState);
}

function updateGrapesJSPreviewStateButtons(buttons, state) {
	var stateButtons = buttons && buttons.length ? buttons : document.querySelectorAll('[data-subin-gjs-preview-state]');

	stateButtons.forEach(function (button) {
		var isActive = button.getAttribute('data-subin-gjs-preview-state') === state;
		button.classList.toggle('is-active', isActive);
		button.setAttribute('aria-pressed', isActive ? 'true' : 'false');
	});
}

function scheduleGrapesJSPreviewStateRefresh(editor) {
	if (!editor || !editor.__subinPreviewState || editor.__subinPreviewState === 'normal') {
		return;
	}

	window.clearTimeout(editor.__subinPreviewStateTimer);
	editor.__subinPreviewStateTimer = window.setTimeout(function () {
		applyGrapesJSPreviewState(editor, editor.__subinPreviewState);
	}, 0);
}

function applyGrapesJSPreviewState(editor, state) {
	var wrapper = editor && editor.getWrapper ? editor.getWrapper() : null;
	var wrapperEl = wrapper && wrapper.view ? wrapper.view.el : null;
	var attributes = wrapper && wrapper.getAttributes ? wrapper.getAttributes() : {};
	var normalizedState = ['normal', 'error', 'success'].indexOf(state) !== -1 ? state : 'normal';

	if (!wrapperEl) {
		return;
	}

	clearGrapesJSPreviewStateDom(wrapperEl);
	wrapperEl.classList.add('subin-preview-state-' + normalizedState);

	if (normalizedState === 'error') {
		renderGrapesJSErrorPreview(editor, wrapperEl, attributes);
	} else if (normalizedState === 'success') {
		insertGrapesJSPreviewMessage(
			wrapperEl,
			'success',
			attributes['data-subin-success-message'] || 'Thanks, your message has been sent.'
		);
	}
}

function clearGrapesJSPreviewStateDom(wrapperEl) {
	if (!wrapperEl) {
		return;
	}

	wrapperEl.classList.remove('subin-preview-state-normal', 'subin-preview-state-error', 'subin-preview-state-success');
	wrapperEl.querySelectorAll('.subin-gjs-preview-state-message,.subin-gjs-preview-field-error').forEach(function (node) {
		node.remove();
	});
	wrapperEl.querySelectorAll('.is-error').forEach(function (node) {
		node.classList.remove('is-error');
	});
}

function renderGrapesJSErrorPreview(editor, wrapperEl, formAttributes) {
	insertGrapesJSPreviewMessage(
		wrapperEl,
		'error',
		formAttributes['data-subin-validation-error-message'] || 'Please check the highlighted fields and try again.'
	);

	grapesJSControlledFields(editor).forEach(function (field) {
		var attributes = field.getAttributes ? field.getAttributes() : {};
		var required = attributes['data-subin-required'] === '1' || attributes['data-subin-required'] === true;
		var fieldEl = field && field.view ? field.view.el : null;
		var message;

		if (!required || !fieldEl) {
			return;
		}

		fieldEl.classList.add('is-error');
		message = attributes['data-subin-required-message'] || formAttributes['data-subin-required-error-message'] || 'This field is required.';
		insertGrapesJSFieldError(fieldEl, message);
	});
}

function insertGrapesJSPreviewMessage(wrapperEl, type, text) {
	var doc = wrapperEl.ownerDocument || document;
	var message = doc.createElement('div');

	message.className = 'subin-gjs-preview-state-message subin-gjs-preview-state-message--' + type + ' subin-form-message subin-form-message--' + type;
	message.setAttribute('role', type === 'error' ? 'alert' : 'status');
	message.textContent = text || '';
	wrapperEl.insertBefore(message, wrapperEl.firstChild);
}

function insertGrapesJSFieldError(fieldEl, text) {
	var doc = fieldEl.ownerDocument || document;
	var error = doc.createElement('p');

	error.className = 'subin-gjs-preview-field-error subin-field-error';
	error.textContent = text || 'This field is required.';
	fieldEl.appendChild(error);
}

function grapesJSControlledFields(editor) {
	var wrapper = editor && editor.getWrapper ? editor.getWrapper() : null;
	var fields = [];

	if (!wrapper) {
		return fields;
	}

	walkComponents(wrapper.components && wrapper.components(), function (component) {
		if (controlledStyleComponentType(component) === 'field') {
			fields.push(component);
		}
	});

	return fields;
}
