(function () {
	'use strict';

	var submittingAttr = 'data-subin-submitting';
	var originalTextAttr = 'data-subin-original-text';
	var recaptchaReadyAttr = 'data-subin-recaptcha-ready';
	var recaptchaPendingAttr = 'data-subin-recaptcha-pending';
	var recaptchaErrorMessage = 'Could not verify the submission. Please try again.';

	function submitButtons(form) {
		return Array.prototype.slice.call(form.querySelectorAll('button[type="submit"], input[type="submit"]'));
	}

	function buttonText(button) {
		return button.tagName === 'INPUT' ? button.value : button.textContent;
	}

	function setButtonText(button, text) {
		if (button.tagName === 'INPUT') {
			button.value = text;
			return;
		}

		button.textContent = text;
	}

	function setSubmitting(form) {
		if (form.getAttribute(submittingAttr) === '1') {
			return false;
		}

		form.setAttribute(submittingAttr, '1');
		form.classList.add('subin-form--submitting');

		submitButtons(form).forEach(function (button) {
			if (!button.hasAttribute(originalTextAttr)) {
				button.setAttribute(originalTextAttr, buttonText(button));
			}
			button.disabled = true;
			setButtonText(button, 'Sending...');
		});

		return true;
	}

	function clearSubmitting(form) {
		form.removeAttribute(submittingAttr);
		form.classList.remove('subin-form--submitting');

		submitButtons(form).forEach(function (button) {
			if (button.hasAttribute(originalTextAttr)) {
				setButtonText(button, button.getAttribute(originalTextAttr));
			}
			button.disabled = false;
		});
	}

	function lockSuccessForm(form) {
		form.setAttribute(submittingAttr, '1');
		form.classList.add('subin-form--submitting');
		submitButtons(form).forEach(function (button) {
			button.disabled = true;
		});
	}

	function formHasSuccess(form) {
		var message = form.querySelector('.subin-form-message--success');
		return !!(message && message.textContent.trim() !== '');
	}

	function messageElement(form) {
		return form.querySelector('.subin-form-message');
	}

	function setMessage(form, status, text) {
		var message = messageElement(form);
		if (!message) {
			return;
		}

		message.classList.remove('subin-form-message--success', 'subin-form-message--error');
		if (status) {
			message.classList.add('subin-form-message--' + status);
		}
		message.textContent = text || '';
	}

	function clearAjaxErrors(form) {
		Array.prototype.slice.call(form.querySelectorAll('.subin-field--error, .is-error')).forEach(function (field) {
			field.classList.remove('subin-field--error', 'is-error');
		});

		Array.prototype.slice.call(form.querySelectorAll('.subin-field-error--ajax')).forEach(function (error) {
			error.parentNode.removeChild(error);
		});

		Array.prototype.slice.call(form.querySelectorAll('[aria-invalid="true"]')).forEach(function (input) {
			input.removeAttribute('aria-invalid');
		});
	}

	function fieldGroupsByKey(form, key) {
		return Array.prototype.slice.call(form.querySelectorAll('[data-subin-field-key]')).filter(function (node) {
			var part = node.getAttribute('data-subin-part');
			return node.getAttribute('data-subin-field-key') === key && (part === 'field_group' || node.classList.contains('subin-field') || node.classList.contains('subin-field-group'));
		});
	}

	function applyAjaxErrors(form, errors) {
		if (!errors || typeof errors !== 'object') {
			return;
		}

		Object.keys(errors).forEach(function (key) {
			var groups = fieldGroupsByKey(form, key);
			groups.forEach(function (group) {
				group.classList.add(group.classList.contains('subin-field-group') ? 'is-error' : 'subin-field--error');
				var input = group.querySelector('[name="subin_fields[' + key + ']"], [name="subin_fields[' + key + '][]"]');
				if (input) {
					input.setAttribute('aria-invalid', 'true');
				}
				var error = document.createElement('p');
				error.className = 'subin-field-error subin-field-error--ajax';
				error.textContent = errors[key];
				group.appendChild(error);
			});
		});
	}

	function submitAjax(form) {
		var restUrl = form.getAttribute('data-subin-rest-url');
		if (!restUrl || !window.fetch || !window.FormData) {
			return false;
		}

		if (!setSubmitting(form)) {
			return true;
		}

		clearAjaxErrors(form);
		setMessage(form, '', '');

		var formData = new window.FormData(form);
		if (formData.has('subin_company_website')) {
			formData.set('subin_company_website', '');
		}
		formData.set('subin_source_url', cleanSourceUrl(window.location.href));

		window.setTimeout(function () {
			window.fetch(restUrl, {
				method: 'POST',
				body: formData,
				credentials: 'same-origin'
			}).then(function (response) {
				return response.json();
			}).then(function (payload) {
				clearRecaptchaToken(form);
				var result = payload && payload.result ? payload.result : {};
				var status = result.status === 'success' ? 'success' : 'error';
				setMessage(form, status, result.message || '');

				if (status === 'success') {
					clearSubmitting(form);
					return;
				}

				applyAjaxErrors(form, result.errors || {});
				clearSubmitting(form);
			}).catch(function () {
				clearRecaptchaToken(form);
				setMessage(form, 'error', 'Your submission could not be sent. Please try again.');
				clearSubmitting(form);
			});
		}, ajaxSubmitDelay(form));

		return true;
	}

	function recaptchaConfig() {
		return window.subinFrontend && window.subinFrontend.recaptcha ? window.subinFrontend.recaptcha : {};
	}

	function recaptchaEnabled() {
		var config = recaptchaConfig();
		return !!(config.enabled && config.siteKey);
	}

	function recaptchaAction() {
		return recaptchaConfig().action || 'submission_inbox_form';
	}

	function setHiddenValue(form, name, value) {
		var input = form.querySelector('[name="' + name + '"]');
		if (!input) {
			input = document.createElement('input');
			input.type = 'hidden';
			input.name = name;
			form.appendChild(input);
		}
		input.value = value;
	}

	function clearRecaptchaToken(form) {
		form.removeAttribute(recaptchaReadyAttr);
		setHiddenValue(form, 'subin_recaptcha_token', '');
	}

	function executeRecaptcha(form) {
		var config = recaptchaConfig();

		return new Promise(function (resolve, reject) {
			if (!window.grecaptcha || !window.grecaptcha.ready || !window.grecaptcha.execute) {
				reject(new Error('recaptcha_unavailable'));
				return;
			}

			window.grecaptcha.ready(function () {
				window.grecaptcha.execute(config.siteKey, { action: recaptchaAction() }).then(function (token) {
					if (!token) {
						reject(new Error('recaptcha_empty_token'));
						return;
					}
					setHiddenValue(form, 'subin_recaptcha_token', token);
					setHiddenValue(form, 'subin_recaptcha_action', recaptchaAction());
					form.setAttribute(recaptchaReadyAttr, '1');
					resolve();
				}).catch(function () {
					reject(new Error('recaptcha_execute_failed'));
				});
			});
		});
	}

	function showRecaptchaError(form) {
		var config = recaptchaConfig();
		setMessage(form, 'error', config.errorMessage || recaptchaErrorMessage);
	}

	function ajaxSubmitDelay(form) {
		var startedAtInput = form.querySelector('[name="subin_started_at"]');
		var startedAt = startedAtInput ? parseInt(startedAtInput.value, 10) : 0;
		var elapsed = startedAt > 0 ? Math.floor(Date.now() / 1000) - startedAt : 2;

		return elapsed >= 2 ? 0 : (2 - elapsed) * 1000;
	}

	function cleanSourceUrl(url) {
		try {
			var parsed = new URL(url);
			parsed.searchParams.delete('subin_form_result');
			return parsed.toString();
		} catch (error) {
			return url;
		}
	}

	document.addEventListener('submit', function (event) {
		var form = event.target && event.target.closest ? event.target.closest('.subin-form') : null;
		if (!form) {
			return;
		}

		if (recaptchaEnabled() && form.getAttribute(recaptchaReadyAttr) !== '1') {
			event.preventDefault();
			if (form.getAttribute(recaptchaPendingAttr) === '1' || form.getAttribute(submittingAttr) === '1') {
				return;
			}

			form.setAttribute(recaptchaPendingAttr, '1');
			clearAjaxErrors(form);
			setMessage(form, '', '');

			if (!setSubmitting(form)) {
				form.removeAttribute(recaptchaPendingAttr);
				return;
			}

			executeRecaptcha(form).then(function () {
				form.removeAttribute(recaptchaPendingAttr);
				if (form.getAttribute('data-subin-ajax') === '1') {
					clearSubmitting(form);
					submitAjax(form);
					return;
				}
				form.submit();
			}).catch(function () {
				form.removeAttribute(recaptchaPendingAttr);
				form.removeAttribute(recaptchaReadyAttr);
				showRecaptchaError(form);
				clearSubmitting(form);
			});
			return;
		}

		if (form.getAttribute('data-subin-ajax') === '1' && submitAjax(form)) {
			event.preventDefault();
			return;
		}

		if (form.getAttribute(submittingAttr) === '1') {
			event.preventDefault();
			return;
		}

		setSubmitting(form);

		window.setTimeout(function () {
			if (event.defaultPrevented) {
				clearSubmitting(form);
			}
		}, 0);
	});

	document.addEventListener('invalid', function (event) {
		var form = event.target && event.target.form && event.target.form.classList.contains('subin-form') ? event.target.form : null;
		if (form) {
			clearSubmitting(form);
		}
	}, true);

	document.addEventListener('DOMContentLoaded', function () {
		Array.prototype.slice.call(document.querySelectorAll('.subin-form')).forEach(function (form) {
			if (formHasSuccess(form)) {
				lockSuccessForm(form);
			}
		});
	});

	window.addEventListener('pageshow', function (event) {
		if (!event.persisted) {
			return;
		}

		Array.prototype.slice.call(document.querySelectorAll('.subin-form')).forEach(function (form) {
			if (formHasSuccess(form)) {
				lockSuccessForm(form);
			} else {
				clearSubmitting(form);
			}
		});
	});
})();
