import autosize from '../vendor/autosize.js'
import formcraftValidation from './formcraft.validation.js'
import helpers from './helpers.js'

function globalNotification(type, message) {
	type = type === 'error' ? 'red' : 'green'
	jQuery('#notification-panel').removeClass('red green').addClass(type).html(message)
}

if (typeof Object.assign !== 'function') {
	Object.assign = function(target) {
		'use strict'
		if (target === null) {
			throw new TypeError('Cannot convert undefined or null to object')
		}

		target = Object(target)
		for (let index = 1; index < arguments.length; index++) {
			let source = arguments[index]
			if (source !== null) {
				for (let key in source) {
					if (Object.prototype.hasOwnProperty.call(source, key)) {
						target[key] = source[key]
					}
				}
			}
		}
		return target
	}
}

class FormCraft {

	constructor(form) {
		this.form = form
		this.formID = form.attr('data-id')
		this.parentElement = form.parents('.form-live')
		let self = this

		// Setup complex form elements
		this.setupInputMasks()
		this.setupCharacterCount()
		this.setupSliderFields()
		this.setupDatepickerFields()
		this.setupFileUploadFields()
		this.setupTimepickerFields()
		this.setupAddressFields()
		form.find('.star-cover label').removeClass('fake-click fake-hover active')
		this.form.find('.textarea-cover textarea').each(function() {
			autosize(this)
		}).on('input', function() {
			let evt = document.createEvent('Event')
			evt.initEvent('autosize:update', true, false)
			this.dispatchEvent(evt)
		})

		// Simple Stuff
		if (jQuery().tooltip) {
			if (helpers.isMobile() === true) {
				this.parentElement.find('.fc-form [data-toggle="tooltip"]').tooltip({
					container: '.fc-form',
					placement: 'top'
				})
			} else {
				this.parentElement.find('.fc-form [data-toggle="tooltip"]').tooltip({
					container: '.fc-form'
				})
			}
		}

		// Parse form text to look for math formulas in []
		this.prepareMathFormulas()

		// Handle form submission
		jQuery(this.form).on('submit', function(event) {
			event.preventDefault()
			FormCraftSubmitForm(self.form, 'all')
		})

		jQuery(this.form).find('span.error').text('')
		setTimeout(function() {
			jQuery(this.form).find('.form-element.error-field').removeClass('error-field')
		}, 300)

		// Auto-save form progress data every 3 seconds
		if (self.form.hasClass('save-form-true')) {
			setInterval(self.saveProgress.bind(self), 3000)
		}

		// Our logic is stored as plain text in a hidden element. Retrieve that.
		let logicText = this.parentElement.find('.form-logic').text().replace(/“/g, '"').replace(/”/g, '"').replace(/″/g, '"').replace(/„/g, '"').replace(/″/g, '"')
		this.FormCraftLogic = logicText.trim() === '' ? {} : jQuery.parseJSON(logicText)
		this.parentElement.find('.form-logic').remove()

		// Check if we need to execute Conditional Logic or Math Logic on changes in fields
		form.on('input', '.oneLineText-cover input[type="text"], .address-cover input[type="text"], .password-cover input[type="password"], .datepicker-cover input[type="text"], .email-cover input[type="text"], .email-cover input[type="email"], .textarea-cover textarea', function() {
			self.setValue = []
			self.checkIfApplyMath(jQuery(this))
			self.checkIfApplyLogic(jQuery(this))
		})
		form.on('change', '.customText-cover input[type="hidden"], .timepicker-cover input[type="hidden"], .slider-cover input[type="hidden"], .fileupload-cover input[type="hidden"], .checkbox-cover input[type="radio"], .star-cover input[type="radio"], .thumb-cover input[type="radio"], .checkbox-cover input[type="checkbox"], .dropdown-cover select', function() {
			self.setValue = []
			self.checkIfApplyMath(jQuery(this))
			self.checkIfApplyLogic(jQuery(this))
		})

		// If form had previously saved data, populate it in the form
		setTimeout(function() {
			let data = {}
			self.form.parents('.form-live').find('.pre-populate-data').each(function() {
				let dataTemp = jQuery(this).text().replace(/“/g, '"').replace(/”/g, '"')
				dataTemp = jQuery.parseJSON(dataTemp)
				for (let field in dataTemp) {
					if (dataTemp[field] === '' || (typeof dataTemp[field] === 'object' && dataTemp[field][0] === '')) {
						delete dataTemp[field]
					}
				}
				data = Object.assign(data, dataTemp)
			})
			self.setFormValues(data)
		}, 0)

		form.keypress(function(event) {
			if (event.which === 13 && form.hasClass('disable-enter-true') === true) {
				event.preventDefault()
			}
		})

		// HoneyPot
		this.form.find('.required_field').hide()

		// Mark ReadOnly
		this.form.find('[make-read-only="true"]').attr('readonly', true).addClass('is-read-only')
	}

	disableSubmit() {
		this.form.find('.submit-button').attr('disabled', true)
	}

	enableSubmit() {
		this.form.find('.submit-button').attr('disabled', false)
	}

	setupCharacterCount() {
		this.form.find('.textarea-cover textarea').on('input', function() {
			let len = jQuery(this).val().length
			let max = parseInt(jQuery(this).parents('.textarea-cover').find('.count-true > span.max-count').text(), 10)
			if (len > max) {
				jQuery(this).parents('.textarea-cover').find('.count-true').css('color', 'red')
			} else {
				jQuery(this).parents('.textarea-cover').find('.count-true').css('color', 'inherit')
			}
			jQuery(this).parents('.textarea-cover').find('.count-true > span.current-count').text(len)
		})
	}

	setupInputMasks() {
		this.form.find('[data-input-mask]').each(function() {
			let options =  {
				onComplete: (cep, event) => {
					jQuery(event.srcElement).removeClass('mask-invalid')
				},
				onChange: (cep, event) => {
					jQuery(event.srcElement).addClass('mask-invalid')
				}
			}
			if (jQuery(this).attr('data-input-mask').replace(/[^a-zA-Z0-9 ():\-\/]+/g, '').trim() !== '') {
				jQuery(this).mask(jQuery(this).attr('data-input-mask').replace(/[^a-zA-Z0-9 ():\-\/]+/g, ''), options)
			}
		})
	}

	setupSliderFields() {
		this.form.find('.slider-cover .ui-slider-cover').each(function() {
			let options = {}
			options.min = parseFloat(jQuery(this).find('> span').attr('range-min'))
			options.max = parseFloat(jQuery(this).find('> span').attr('range-max'))
			options.step = parseFloat(jQuery(this).find('> span').attr('range-step'))
			options.range = jQuery(this).find('> span').attr('range-true') === 'true' ? true : 'min'
			let prefix = jQuery(this).find('> span').attr('data-prefix') || ''
			let suffix = jQuery(this).find('> span').attr('data-suffix') || ''
			options.create = function() {
				if (options.range === true) {
					jQuery(this).find('.ui-slider-range').eq(0).append('<span class="ui-slider-handle-nos">0</span>')
				} else {
					jQuery(this).find('span.ui-slider-handle').eq(0).append('<span class="ui-slider-handle-nos">0</span>')
				}
				jQuery(this).parents('.slider-cover').find('input[type="hidden"]').val('').trigger('change').attr('data-prefix', prefix).attr('data-suffix', suffix)
			}
			options.change = options.slide = function(event, ui) {
				jQuery(this).parents('.ui-slider-cover').find('.ui-slider-handle-nos').show()
				let thousand = jQuery(this).parents('.fc-form').attr('data-thousand')
				let decimal = jQuery(this).parents('.fc-form').attr('data-decimal')
				jQuery(this).parents('.slider-cover').find('.ui-slider-handle-nos').css('margin-left', `-${(jQuery(this).parents('.slider-cover').find('.ui-slider-handle-nos').outerWidth() / 2 - 9)}px`)
				let value, valueAmount, valueOne, valueOneFrom, valueZero, valueZeroFrom

				if (ui.values) {
					valueAmount = `${ui.values[0]} - ${ui.values[1]}`
					valueZero = ui.values[0].toString().replace(/[.]/g, decimal).replace(/\B(?=(\d{3})+(?!\d))/g, thousand)
					valueOne = ui.values[1].toString().replace(/[.]/g, decimal).replace(/\B(?=(\d{3})+(?!\d))/g, thousand)
					valueZeroFrom = ui.values[0]
					valueOneFrom = ui.values[1]
					ui.values[0] = prefix + ui.values[0] + suffix
					ui.values[1] = prefix + ui.values[1] + suffix
					value = `${ui.values[0]} - ${ui.values[1]}`
				} else {
					valueAmount = ui.value
					value = parseFloat(ui.value)
					valueZero = value.toString().replace(/[.]/g, decimal).replace(/\B(?=(\d{3})+(?!\d))/g, thousand)
					valueZeroFrom = value
					valueOne = ''
					valueOneFrom = ''
					value = prefix + value + suffix
				}
				jQuery(this).parents('.slider-cover').find('input').val(valueAmount).trigger('change')
				value = value.replace(valueZeroFrom, valueZero).replace(valueOneFrom, valueOne)
				jQuery(this).parents('.slider-cover').find('.ui-slider-handle-nos').text(value)
			}
			jQuery(this).html('<span></span>')
			jQuery(this).find('span').slider(options)
		})
	}

	setupDatepickerFields() {
		this.form.find('.datepicker-cover input[type="text"]').each(function () {
			jQuery(this).removeClass('hasDatepicker')
			let options = {}
			options.beforeShow = function() {
				jQuery('#ui-datepicker-div').removeClass('ui-datepicker').addClass('formcraft-datepicker')
			}
			options.onClose = function () {
				jQuery(this).trigger('blur')
			}
			options.onSelect = function() {
				jQuery(this).trigger('change').trigger('input')
				if (jQuery(`[data-date-min-range="[${jQuery(this).attr('data-field-id')}]"]`).length !== 0 && jQuery(`[data-date-min-range="[${jQuery(this).attr('data-field-id')}]"]`).hasClass('hasDatepicker')) {
					jQuery(`[data-date-min-range="[${jQuery(this).attr('data-field-id')}]"]`).datepicker(
						'option',
						'minDate',
						jQuery(this).datepicker('getDate')
					)
				}
			}
			if (jQuery(this).attr('data-date-lang') && jQuery(this).attr('data-date-lang') !== 'en' && window.datepickerLoad === false) {
				jQuery.getScript(`${FC.datepickerLang}datepicker-${jQuery(this).attr('data-date-lang')}.js`)
				window.datepickerLoad = true
			}
			if (jQuery(this).attr('data-date-format')) {
				options.dateFormat = jQuery(this).attr('data-date-format')
			}

			if (jQuery(this).attr('data-date-max')) {
				let maxDate
				if (jQuery(this).attr('data-date-max') !== '' && parseInt(jQuery(this).attr('data-date-max'), 10).toString() === jQuery(this).attr('data-date-max')) {
					maxDate = new Date()
					maxDate.setDate(maxDate.getDate() + parseInt(jQuery(this).attr('data-date-max'), 10))
				} else {
					maxDate = new Date(jQuery(this).attr('data-date-max-alt'))
				}
				options.maxDate = maxDate
			}
			if (jQuery(this).attr('data-date-min')) {
				let minDate
				if (jQuery(this).attr('data-date-min') !== '' && parseInt(jQuery(this).attr('data-date-min'), 10).toString() === jQuery(this).attr('data-date-min')) {
					minDate = new Date()
					minDate.setDate(minDate.getDate() + parseInt(jQuery(this).attr('data-date-min'), 10))
				} else {
					minDate = new Date(jQuery(this).attr('data-date-min-alt'))
				}
				options.minDate = minDate
			}
			if (jQuery(this).attr('data-date-days')) {
				let tempNew = jQuery.map(jQuery.parseJSON(jQuery(this).attr('data-date-days')), (x, y) => {
					if (x === true) return y
				})
				options.beforeShowDay = function(date) {
					if (tempNew.indexOf(date.getDay().toString()) !== -1) return [true, '']
					return [false, '']
				}
			}
			options.nextText = '❯'
			options.prevText = '❮'
			options.hideIfNoPrevNext = true
			options.changeYear = true
			options.changeMonth = true
			options.showAnim = false
			options.yearRange = 'c-100:c+100'
			options.shortYearCutoff = 50
			options.showOtherMonths = true
			jQuery(this).datepicker(options)
		})
	}

	setupFileUploadFields() {
		if (this.form.find('.fileupload-cover .button-file input').length === 0) return
		this.form.find('.fileupload-cover .button-file input').fileupload({
			dataType: 'json',
			add: function (e, data) {
				let thisForm = jQuery(this).parents('form').data('FormCraft')
				thisForm.disableSubmit()
				if (jQuery(this).attr('data-allow-extensions') !== '' && jQuery(this).attr('data-allow-extensions').indexOf(',')) {
					let extensions = jQuery(this).attr('data-allow-extensions').replace(/ /g, '').split(',')
					for (let file in data.files) {
						let fileParts = data.files[file].name.split('.')
						let fileExtension = fileParts[fileParts.length - 1]
						if (extensions.indexOf(fileExtension.toLowerCase()) === -1) {
							thisForm.enableSubmit()
							return false
						}
					}
				}
				if (jQuery(this).attr('data-max-files') !== '') {
					if (jQuery(this).parent().parent().find('.files-list li').length >= parseInt(jQuery(this).attr('data-max-files'), 10)) {
						thisForm.enableSubmit()
						return false
					}
				}

				if (typeof jQuery(this).attr('data-max-size') !== 'undefined' && jQuery(this).attr('data-max-size') !== '') {
					let maxSize = parseFloat(jQuery(this).attr('data-max-size'))
					if ((data.files[0].size / 1024) > maxSize) {
						if (typeof FC.validation.max_file_size === 'undefined') {
							alert('File too big')
						} else {
							alert(FC.validation.max_file_size.replace('[x]', maxSize))
						}
						thisForm.enableSubmit()
						return false
					}
				}

				let id = jQuery(this).parents('.fc-form').attr('data-id')
				data.url = `${FC.ajaxurl}${FC.ajaxurl.indexOf('?') === -1 ? '?' : '&'}action=formcraft3_file_upload&id=${id}`
				let parent = jQuery(this).parent().parent()
				if (parent.find('.files-list').length === 0) {
					parent.append('<ul class="files-list"></ul>')
				}
				parent.find('.files-list').append('<li><div></div></li>')
				data.listPosition = parent.find('li').length - 1
				parent.find('.files-list li').eq(data.listPosition).slideDown(100)
				data.timeout = 0
				window.jqXHR = data.submit()
			},
			progress: function (e, data) {
				let parent = jQuery(this).parent().parent()
				let progress = parseInt(data.loaded / data.total * 100, 10)
				parent.find('.files-list li').eq(data.listPosition).find('div').css('width', `${progress}%`)
			},
			done: function (e, data) {
				let thisForm = jQuery(this).parents('form').data('FormCraft')
				thisForm.enableSubmit()
				let parent = jQuery(this).parent().parent()
				if (data.result.success) {
					let name = jQuery(this).attr('data-name-list')
					parent.find('.files-list li').eq(data.listPosition).find('div').text(data.result.file_name)
					parent.find('.files-list li').eq(data.listPosition).append(`<span class="delete-file" title="Delete File">&times;</span><input type="hidden" data-field-id="${name}" name="${name}[]" value="${data.result.success}"/>`)
					parent.find('.files-list li').eq(data.listPosition).find('input').trigger('change')
				} else if (data.result.failed) {
					parent.find('.files-list li').eq(data.listPosition).remove()
					if (showDebug === true) {
						globalNotification('error', data.result.debug)
					}
				}
			}
		})
		this.form.find('.fileupload-cover').on('click', '.files-list .delete-file', function() {
			let key = jQuery(this).parent().find('input').val()
			jQuery(this).addClass('icon-spin5 animate-spin').html('')
			jQuery.ajax({
				url: FC.ajaxurl,
				type: 'POST',
				context: jQuery(this),
				data: `action=formcraft3_file_delete&id=${key}`,
				dataType: 'json'
			})
			.done(function(response) {
				if (response.success) {
					jQuery(this).parent().slideUp(200, function() {
						jQuery(this).find('input').val('').trigger('change')
						jQuery(this).remove()
					})
				} else {
					jQuery(this).removeClass('icon-spin5 animate-spin').html('×')
				}
			})
			.always(function() {
				jQuery(this).removeClass('icon-spin5 animate-spin').html('×')
			})
		})
	}

	setupTimepickerFields() {
		this.form.on('input, change', '.time-fields-cover > select, .time-fields-cover > input', function() {
			let parent = jQuery(this).parent()
			let hrs = parent.find('select').eq(0).val()
			let minute = parent.find('select').eq(1).val()
			let meridian = parent.find('input').val()
			if (jQuery(this).parent().hasClass('hide-meridian-true')) {
				parent.parent().find('input[type="hidden"]').val(`${hrs}:${minute}`).trigger('change')
			} else {
				parent.parent().find('input[type="hidden"]').val(`${hrs}:${minute} ${meridian}`).trigger('change')
			}
		})
		this.form.on('focus', '.meridian-picker', function() {
			if (jQuery(this).val() === 'am') {
				jQuery(this).val('pm').trigger('change')
			} else if (jQuery(this).val() === 'pm') {
				jQuery(this).val('am').trigger('change')
			} else {
				jQuery(this).val('am').trigger('change')
			}
			jQuery(this).blur()
			jQuery(this).trigger('input')
		})
	}

	setupAddressFields() {
		if (typeof AddressPicker === 'undefined') {
			jQuery('.address-picker-field').parents('.field-cover').find('.address-field-map').html('You need to enter the Google API Key when editing the field to make the autocomplete address field work').css('height', 'auto').css('color', 'red')
			return
		}
		jQuery('.address-picker-field').each(function() {
			if (jQuery(this).attr('data-show-map') === 'true') {
				jQuery(this).parents('.field-cover').find('.address-field-map').css('height', jQuery(this).attr('data-map-height'))
				jQuery(this).data('addressField', new AddressPicker({
					map: {
						id: jQuery(this).parents('.field-cover').find('.address-field-map')[0]
					},
					reverseGeocoding: true
				}))
				jQuery(this).typeahead(null, {
					displayKey: 'description',
					source: jQuery(this).data('addressField').ttAdapter()
				})
				jQuery(this).bind('typeahead:selected', jQuery(this).data('addressField').updateMap)
				jQuery(this).bind('typeahead:cursorchanged', jQuery(this).data('addressField').updateMap)
				jQuery(jQuery(this).data('addressField')).on('addresspicker:selected', (event, result) => {
					jQuery(this).parents('.address-cover').find('.address-picker-field-hidden').val(result.placeResult.formatted_address)
					jQuery(this).val(result.address())
				})
			} else {
				jQuery(this).data('addressField', new AddressPicker())
				jQuery(this).typeahead(null, {
					displayKey: 'description',
					source: jQuery(this).data('addressField').ttAdapter()
				})
				jQuery(this).parents('.field-cover').find('.address-field-map').hide()
				jQuery(this).bind('typeahead:selected', jQuery(this).data('addressField').updateMap)
				jQuery(this).bind('typeahead:cursorchanged', jQuery(this).data('addressField').updateMap)
				jQuery(jQuery(this).data('addressField')).on('addresspicker:selected', (event, result) => {
					jQuery(this).parents('.address-cover').find('.address-picker-field-hidden').val(result.placeResult.formatted_address)
					jQuery(this).val(result.address())
				})
			}
		})
	}

	prepareMathFormulas() {
		this.FormCraftMath = []
		let self = this
		this.form.find('.customText-cover > div, .stripe-cover div.stripe-amount-show, .stripe-cover input.stripe-amount-hidden, .customText-cover input[type="hidden"], .allow-math').each(function() {
			let html, match, text, textToSearch
			if (jQuery(this).prop('type') === 'hidden') {
				text = textToSearch = jQuery(this).val()
			} else {
				text = jQuery(this).text()
				html = jQuery(this).html()
				let temp = jQuery('<div>').html(html)
				temp.find('.fc-third-party').remove()
				textToSearch = temp.text()
			}
			let pattern = /\[(.*?)\]/g
			while ((match = pattern.exec(textToSearch)) !== null) {
				match[0] = jQuery('<div/>').text(match[0]).html()
				let identifier = Math.random().toString(36).replace(/[^a-z]+/g, '').substring(0, 8)
				if (jQuery(this).prop('type') === 'hidden') {
					jQuery(this).attr('id', `bind-math-${identifier}`).val('')
				} else {
					html = html.replace(match[0], `<span id="bind-math-${identifier}"></span>`)
					jQuery(this).html(html)
				}

				self.FormCraftMath[identifier] = { identifier: identifier, variables: [] }
				self.FormCraftMath[identifier].string = match[1].replace(/[^a-zA-Z0-9.*()\-,+\/]+/g, '').toLowerCase()
				if (self.FormCraftMath[identifier].string.slice(-1).replace(/[^.*\-,+\/]+/g, '') !== '') {
					self.FormCraftMath[identifier].string = self.FormCraftMath[identifier].string.slice(0, self.FormCraftMath[identifier].string.length - 1)
				}
				if (self.FormCraftMath[identifier].string.replace(/[^.*()\-,+\/]+/g, '') === '') {
					self.FormCraftMath[identifier].resultType = 'string'
				} else {
					self.FormCraftMath[identifier].resultType = 'math'
				}
				let fields = self.FormCraftMath[identifier].string.split(/[*()\-,+\/]/)
				for (let field in fields) {
					if (fields[field] === '' || typeof fields[field] === 'function' || fields[field].replace(/[^\d.-]/g, '') === fields[field]) {
						continue
					}
					self.FormCraftMath[identifier].variables.push(fields[field])
				}
				self.FormCraftMath[identifier].variables = self.FormCraftMath[identifier].variables.sort(function(a, b) {
					return parseInt(b.replace('field', ''), 10) - parseInt(a.replace('field', ''), 10)
				})
			}
		})
	}

	checkIfApplyMath(element) {
		let fieldID = jQuery(element).attr('data-field-id')
		for (let formula in this.FormCraftMath) {
			for (let field in this.FormCraftMath[formula].variables) {
				if (this.FormCraftMath[formula].variables[field] === fieldID) {
					this.calculateAndApplyMath(this.FormCraftMath[formula])
				}
			}
		}
	}

	calculateAndApplyMath(formula) {
		let mathResult
		let form = jQuery(`#bind-math-${formula.identifier}`).parents('form')
		let thousand = jQuery(`#bind-math-${formula.identifier}`).parents('form').attr('data-thousand')
		let decimal = jQuery(`#bind-math-${formula.identifier}`).parents('form').attr('data-decimal')

		if (formula.variables.length === 1 && formula.variables[0] === formula.string) {
			// Do this if the [] block has one variable
			mathResult = this.getFieldValue(jQuery(`[data-field-id="${formula.variables[0]}"]`), 'string')
			if (jQuery(`#bind-math-${formula.identifier}`).prop('type') === 'hidden') {
				mathResult = parseFloat(mathResult)
				setTimeout(() => {
					jQuery(`#bind-math-${formula.identifier}`).val(mathResult).trigger('change')
				})
			} else if (jQuery('.fc-form.spin-true').length && !isNaN(parseFloat(mathResult))) {
				helpers.spinTo(`#bind-math-${formula.identifier}`, mathResult, thousand, decimal)
			} else {
				mathResult = mathResult.toString().replace(/[.]/g, decimal).replace(/\B(?=(\d{3})+(?!\d))/g, thousand)
				jQuery(`#bind-math-${formula.identifier}`).text(mathResult)
			}
			jQuery(document).trigger('formcraft_math_change', [form])
		} else {
			// Do this if the [] block has more than one variable
			let string = formula.string
			for (let field in formula.variables) {
				if (typeof formula.variables[field] === 'function') {
					continue
				}
				let value = this.getFieldValue(jQuery(form).find(`[data-field-id="${formula.variables[field]}"]`), 'number')
				let reg = new RegExp(formula.variables[field], 'g')
				value = value === '' ? 0 : value
				string = string.replace(reg, value)
			}
			string = string.replace(/--/g, '+')
			try {
				mathResult = parseFloat(eval(string).toFixed(2))
			} catch (e) {
				mathResult = 0
				if (e instanceof SyntaxError) {
					console.log(`%cMath Formula Syntax Error. Formula: ${string}. FormID: ${this.formID}. Error: ${e.message}`, 'color: red')
				}
			}
			if (jQuery(`#bind-math-${formula.identifier}`).prop('type') === 'hidden') {
				jQuery(`#bind-math-${formula.identifier}`).val(mathResult).trigger('change')
			} else if (jQuery('.fc-form.spin-true').length) {
				helpers.spinTo(`#bind-math-${formula.identifier}`, mathResult, thousand, decimal)
			} else {
				mathResult = mathResult.toString().replace(/[.]/g, decimal).replace(/\B(?=(\d{3})+(?!\d))/g, thousand)
				jQuery(`#bind-math-${formula.identifier}`).text(mathResult)
			}
			jQuery(document).trigger('formcraft_math_change', [form])
		}
	}

	checkIfApplyLogic(element) {
		let parent = this.form.parents('.form-live').attr('data-uniq')
		let fieldID = jQuery(element).attr('data-field-id')
		let applied = false
		if (typeof this.FormCraftLogic !== 'undefined' && this.FormCraftLogic.length !== 0) {
			for (let logic in this.FormCraftLogic) {
				for (let conditions in this.FormCraftLogic[logic][0]) {
					let tempField = this.FormCraftLogic[logic][0][conditions][2]
					if (typeof tempField !== 'undefined' && tempField.slice(0, 1) === '[' && tempField.replace('[', '').replace(']', '') === fieldID) {
						this.applyLogic(this.FormCraftLogic[logic], parent)
						applied = true
					} else if (this.FormCraftLogic[logic][0][conditions][0] === fieldID) {
						this.applyLogic(this.FormCraftLogic[logic], parent)
						applied = true
					}
				}
			}
		}
		if (applied === true) {
			this.setFormValues(this.setValue)
		}
		if (typeof this.finalHideShowList === 'undefined') {
			return false
		}
		for (let field in this.finalHideShowList) {
			if (this.finalHideShowList[field].length === 0 || typeof this.finalHideShowList[field] === 'function') {
				continue
			}
			this.finalHideShowList[field] = this.finalHideShowList[field].sort()
			let newState = this.finalHideShowList[field][this.finalHideShowList[field].length - 1]
			switch (newState) {

				case 'hide':
				if (!jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('state-hidden')) {
					jQuery(`.uniq-${parent} form .form-element-${field}`).removeClass('state-hidden state-shown over-write')
					jQuery(`.uniq-${parent} form .form-element-${field}`).slideUp(300).addClass('state-hidden')
					jQuery(`.uniq-${parent} form .form-element-${field}`).trigger('hideElement')
				}
				break

				case 'show':
				if (!jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('state-shown')) {
					jQuery(`.uniq-${parent} form .form-element-${field}`).removeClass('state-hidden state-shown over-write')
					jQuery(`.uniq-${parent} form .form-element-${field}`).slideDown(300).addClass('state-shown')
					jQuery(`.uniq-${parent} form .form-element-${field}`).trigger('showElement')
				}
				break

				case 'default':
				if (jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('default-false') && jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('state-hidden')) {
					jQuery(`.uniq-${parent} form .form-element-${field}`).slideDown(300).removeClass('state-hidden state-shown').addClass('state-shown')
					jQuery(`.uniq-${parent} form .form-element-${field}`).trigger('showElement')
				}
				if (jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('default-true') && jQuery(`.uniq-${parent} form .form-element-${field}`).hasClass('state-shown')) {
					jQuery(`.uniq-${parent} form .form-element-${field}`).slideUp(300).removeClass('state-hidden state-shown').addClass('state-hidden')
					jQuery(`.uniq-${parent} form .form-element-${field}`).trigger('hideElement')
				}
				break

			}
		}
		this.finalHideShowList = []
	}

	applyLogic(logic, parent) {
		this.finalHideShowList = this.finalHideShowList || []
		window.finalEmailsTo = window.finalEmailsTo || []
		let logicNos = this.FormCraftLogic.indexOf(logic)
		let conditions = logic[0]
		let actions = logic[1]
		let conditionsSatisfied = 0
		let conditionsToSatisfy = logic[2] === 'or' ? 1 : conditions.length

		for (let x in conditions) {
			let value = this.getFieldValue(jQuery(`.uniq-${parent} [data-field-id="${conditions[x][0]}"]`), 'string')
			let conditionToCheck, tempVal
			conditions[x][2] = conditions[x][2] || ''
			if (conditions[x][2].slice(0, 1) === '[') {
				conditionToCheck = conditions[x][2].replace('[', '').replace(']', '')
				conditionToCheck = this.getFieldValue(jQuery(`[data-field-id="${conditionToCheck}"]`), 'string')
			} else {
				conditionToCheck = conditions[x][2]
			}
			switch (conditions[x][1]) {

				case 'equal_to':
				if (conditionToCheck.toString().indexOf('-') === 4) {
					tempVal = this.dateToDifference(conditionToCheck).toString()
				} else {
					tempVal = conditionToCheck
				}
				if (tempVal === value.toString()) conditionsSatisfied++
				break

				case 'not_equal_to':
				if (conditionToCheck.toString().indexOf('-') === 4) {
					tempVal = this.dateToDifference(conditionToCheck).toString()
				} else {
					tempVal = conditionToCheck
				}
				if (tempVal !== value.toString()) conditionsSatisfied++
				break

				case 'contains':
				if (conditionToCheck === '') {
					if (value !== '') conditionsSatisfied++
					break
				}
				if (value.toString().indexOf(conditionToCheck) !== -1) conditionsSatisfied++
				break

				case 'contains_not':
				if (value.toString().indexOf(conditionToCheck) === -1) conditionsSatisfied++
				break

				case 'greater_than':
				if (conditionToCheck.toString().indexOf('-') !== -1) {
					tempVal = this.dateToDifference(conditionToCheck)
				} else {
					tempVal = conditionToCheck
				}
				if (!isNaN(parseFloat(value)) && parseFloat(value) > parseFloat(tempVal)) conditionsSatisfied++
				break

				case 'less_than':
				if (conditionToCheck.toString().indexOf('-') !== -1) {
					tempVal = this.dateToDifference(conditionToCheck)
				} else {
					tempVal = conditionToCheck
				}
				if (!isNaN(parseFloat(value)) && parseFloat(value) < parseFloat(tempVal)) conditionsSatisfied++
				break
			}
		}
		this.executeLogic(actions, logicNos, conditionsToSatisfy, conditionsSatisfied)
	}

	executeLogic(actions, logicNos, conditionsToSatisfy, conditionsSatisfied) {

		for (let x in actions) {
			switch (actions[x][0]) {

				case 'hide_fields':
				if (!actions[x][1]) continue
				let fieldsToHide = actions[x][1].split(',')
				for (let y in fieldsToHide) {
					if (typeof fieldsToHide[y] === 'function') continue
					this.finalHideShowList[fieldsToHide[y]] = this.finalHideShowList[fieldsToHide[y]] || []
					if (conditionsSatisfied >= conditionsToSatisfy) {
						this.finalHideShowList[fieldsToHide[y]].push('hide')
					} else {
						this.finalHideShowList[fieldsToHide[y]].push('default')
					}
				}
				break

				case 'show_fields':
				if (!actions[x][1]) continue
				let fieldsToShow = actions[x][1].split(',')
				for (let y in fieldsToShow) {
					if (typeof fieldsToShow[y] === 'function') continue
					this.finalHideShowList[fieldsToShow[y]] = this.finalHideShowList[fieldsToShow[y]] || []
					if (conditionsSatisfied >= conditionsToSatisfy) {
						this.finalHideShowList[fieldsToShow[y]].push('show')
					} else {
						this.finalHideShowList[fieldsToShow[y]].push('default')
					}
				}
				break

				case 'email_to':
				if (!actions[x][2]) continue
				let emails = actions[x][2]
				if (conditionsSatisfied >= conditionsToSatisfy) {
					if (window.finalEmailsTo.indexOf(`${logicNos}:${emails}`) === -1) {
						window.finalEmailsTo.push(`${logicNos}:${emails}`)
					}
				} else if (window.finalEmailsTo.indexOf(`${logicNos}:${emails}`) !== -1) {
					window.finalEmailsTo.splice(window.finalEmailsTo.indexOf(`${logicNos}:${emails}`), 1)
				}
				break

				case 'redirect_to':
				window.finalRedirect = window.finalRedirect || []
				if (conditionsSatisfied >= conditionsToSatisfy) {
					window.finalRedirect.push(actions[x][2])
				} else if (window.finalRedirect.indexOf(actions[x][2]) !== -1) {
					window.finalRedirect.splice(window.finalRedirect.indexOf(actions[x][2]), 1)
				}
				break

				case 'trigger_integration':
				if (!actions[x][3]) continue
				window.triggerIntegration = window.triggerIntegration || []
				if (conditionsSatisfied >= conditionsToSatisfy) {
					if (window.triggerIntegration.indexOf(actions[x][3]) === -1) {
						window.triggerIntegration.push(actions[x][3])
					}
				} else if (window.triggerIntegration.indexOf(actions[x][3]) !== -1) {
					window.triggerIntegration.splice(window.triggerIntegration.indexOf(actions[x][3]), 1)
				}
				break

				case 'set_value':
				// if (!actions[x][2]) continue
				this.setValue = this.setValue || []
				let actionsApply
				if (actions[x][2] && actions[x][2].slice(0, 1) === '[') {
					actionsApply = actions[x][2].replace('[', '').replace(']', '')
					actionsApply = this.getFieldValue(jQuery(`[data-field-id="${actionsApply}"]`), 'string')
				} else {
					actionsApply = actions[x][2]
				}
				if (conditionsSatisfied >= conditionsToSatisfy) {
					this.setValue[actions[x][4]] = actionsApply
				} else if (typeof this.setValue[actions[x][4]] !== 'undefined' && this.setValue[actions[x][4]] === actionsApply) {
					// delete this.setValue[actions[x][4]]
				}
				break
			}
		}
	}

	/**
	* Save form data in a JSON string, and store it in the database
	*/
	saveProgress() {
		let data = `${this.form.find('input, textarea, select').not('.no-save, [type="password"], .stripe-amount-hidden').serialize()}&id=${this.form.attr('data-id')}`
		if (!this.lastSaveProgress || this.lastSaveProgress !== data) {
			this.lastSaveProgress = data
		} else {
			return false
		}
		return jQuery.ajax({
			url: FC.ajaxurl,
			type: 'POST',
			data: `action=formcraft_save_form_progress&${data}`,
			dataType: 'json'
		})
	}

	/**
	* Get value of an input field element
	*/
	getFieldValue(element, type) {
		if (jQuery(element).length === 0) {
			return 0
		}
		let elementType = jQuery(element).prop('type')
		let result
		let decimal = jQuery(element).parents('.fc-form').attr('data-decimal') === ',' ? ',' : '.'
		elementType = jQuery(element).is('select') ? 'select' : elementType
		elementType = jQuery(element).hasClass('hasDatepicker') ? 'date' : elementType
		elementType = jQuery(element).parent().parent().hasClass('files-list') ? 'file' : elementType
		elementType = jQuery(element).parent().parent().hasClass('slider-cover') ? 'slider' : elementType
		switch (elementType) {

			case 'text': case 'password': case 'select': case 'hidden': case 'email': case 'textarea':
			result = jQuery(element).val().replace(decimal, '.')
			break

			case 'slider':
			result = jQuery(element).val().replace(decimal, '.')
			if (result.indexOf(' - ') !== -1) {
				result = (parseFloat(result.split(' - ')[0]) + parseFloat(result.split(' - ')[1])) / 2
			}
			break

			case 'radio': case 'checkbox':
			result = []
			jQuery(`[name="${jQuery(element).prop('name')}"]:checked`).each(function() {
				result.push(jQuery(this).val().replace(decimal, '.'))
			})
			break

			case 'date':
			let date = jQuery(element).datepicker('getDate')
			if (date === null) {
				return ''
			}
			let now = new Date()
			let today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
			date = date === null ? today : date
			result = parseInt((date - today) / (60 * 60 * 24 * 1000), 10)
			break

			case 'file':
			let name = jQuery(element).attr('name')
			result = 0
			jQuery(`[name="${name}"]`).each(function() {
				if (jQuery(this).val() !== '') result++
			})
			break

		}
		if (type === 'string') {
			if (typeof result === 'object') return result.join(', ')
			return result
		}
		if (typeof result === 'object') {
			let sum = 0
			for (let x in result) {
				sum = sum + (isNaN(parseFloat(result[x])) ? 0 : parseFloat(result[x]))
			}
			return sum
		} else if (typeof result === 'string' && result.indexOf('-') !== -1) {
			let temp = result.split('-')
			result = (parseFloat(temp[0].trim()) + parseFloat(temp[1].trim())) / 2
			return isNaN(parseFloat(result)) ? 0 : parseFloat(result)
		}
		return isNaN(parseFloat(result)) ? 0 : parseFloat(result)
	}

	/**
	* Set form field values
	* @param {Object} data e.g. {field1: "Jack", field2: "23"}
	*/
	setFormValues(data) {
		let form = this.form
		for (let x in data) {
			let element = form.find(`[name="${x}"]`).length === 0 ? form.find(`[name="${x}[]"]`) : form.find(`[name="${x}"]`)
			let elementType = element.prop('type')
			elementType = element.is('select') ? 'select' : elementType
			elementType = element.hasClass('hasDatepicker') ? 'date' : elementType
			elementType = element.parent().parent().hasClass('files-list') ? 'file' : elementType
			elementType = element.parents('.field-cover').hasClass('slider-cover') ? 'slider' : elementType
			elementType = element.parents('.field-cover').hasClass('timepicker-cover') ? 'timepicker' : elementType
			switch (elementType) {

				case 'text': case 'email': case 'select': case 'hidden': case 'textarea': case 'date':
				if (element.attr('id')) {
					if (element.attr('id').substr(0, 9) === 'bind-math') break
				}
				if (data[x] !== element.val()) {
					element.val(data[x]).trigger('input').trigger('change')
				}
				break

				case 'radio': case 'checkbox':
				if ((typeof data[x] === 'string' && data[x] === '') || (data[x] === null) && form.find(`[name="${x}[]"]`).length > 0) {
					form.find(`[name="${x}[]"]`).prop('checked', false).trigger('change')
				}
				data[x] = typeof data[x] === 'string' ? [data[x]] : data[x]
				for (let y in data[x]) {
					if (form.find(`[name="${x}[]"]`).length === 0) {
						form.find(`[name="${x}"][value="${data[x][y]}"]`).prop('checked', true).trigger('change')
					} else {
						form.find(`[name="${x}[]"][value="${data[x][y]}"]`).prop('checked', true).trigger('change')
					}
				}
				break

				case 'timepicker':
				element.val(data[x]).trigger('change')
				let time = data[x].replace(' ', ':').split(':')
				time[0] = time[0] === '' || typeof time[0] === 'undefined' ? '00' : time[0]
				time[1] = time[1] === '' || typeof time[1] === 'undefined' ? '00' : time[1]
				time[2] = time[2] === '' || typeof time[2] === 'undefined' ? 'am' : time[2]
				element.parents('.timepicker-cover').find('.time-fields-cover > select').eq(0).val(time[0])
				element.parents('.timepicker-cover').find('.time-fields-cover > select').eq(1).val(time[1])
				element.parents('.timepicker-cover').find('.time-fields-cover > input').eq(0).val(time[2])
				break

				case 'slider':
				if (data[x] === '') break
				if (data[x].indexOf(' - ') !== -1) {
					let temp = data[x].split(' - ')
					temp = temp.map((x) => parseFloat(x.replace(/[^\d.-]/g, '')))
					element.parents('.slider-cover').find('.ui-slider-cover > span').slider('values', temp)
				} else {
					data[x] = data[x].replace(element.attr('data-prefix'), '').replace(element.attr('data-suffix'), '')
					data[x] = isNaN(data[x]) ? 0 : parseFloat(data[x].replace(/[^\d.-]/g, ''))
					element.parents('.slider-cover').find('.ui-slider-cover > span').slider('value', data[x])
				}
				break
			}
		}
	}

	/**
	* Save form data in a JSON string, and store it in the database
	* @param (String) date      format YYYY-MM-DD
	* @return (Number) result   difference in days between input data, and today
	*/
	dateToDifference(date) {
		let temp = date.toString().split('-')
		let now = new Date()
		let today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
		let fieldDate = new Date(temp[0], parseInt(temp[1], 10) - 1, temp[2])
		return parseInt((fieldDate - today) / (60 * 60 * 24 * 1000), 10)
	}

}

jQuery(document).ready(function() {
	jQuery('.fc-form').each(function() {
		let thisForm = new FormCraft(jQuery(this))
		jQuery(this).data('FormCraft', thisForm)
	})

	// Fix an issue where autosizing textarea doesn't work when the field is inside an element which is hidden by default
	jQuery('.fc-form-modal').on('shown.bs.fc_modal', function () {
		let form = jQuery(this).find('.fc-form').attr('data-id')
		jQuery(this).find('.fc-form').find('textarea').trigger('input')
		jQuery.get(`${FC.ajaxurl}?action=formcraft3_trigger_view&id=${form}`)
	})
})

/**
* Legacy Support
*/
window.setFormValues = function(form, data) {
	form.data('FormCraft').setFormValues(data)
}

window.datepickerLoad = false

window.showDebug = window.location.href.indexOf('preview=true') > -1 ? true : false

if (window.location.protocol === 'https:') {
	FC.ajaxurl = FC.ajaxurl.replace('http:', 'https:')
	FC.datepickerLang = FC.datepickerLang.replace('http:', 'https:')
}

/**
* Main function to handle form submission
*/
window.FormCraftSubmitForm = function(element, type, callback) {
	let redirect = ''
	let form = jQuery(element)
	if (type === 'all' && form.find('.form-element-type-submit.state-hidden').length === form.find('.form-element-type-submit').length) {
		return false
	}
	let formData = jQuery(element).hasClass('dont-submit-hidden-true') ? form.find('.form-element').not('.state-hidden').find('input, select, textarea').serialize() : form.serialize()
	let hidden = []
	form.find('.form-element.state-hidden').each(function() {
		hidden.push(jQuery(this).attr('data-identifier'))
	})
	hidden = hidden.join(', ')

	let emails = ''
	if (typeof window.finalEmailsTo !== 'undefined') {
		for (let x in window.finalEmailsTo) {
			if (typeof window.finalEmailsTo[x] === 'function') {
				continue
			}
			emails = `${emails},${encodeURIComponent(window.finalEmailsTo[x].substr(window.finalEmailsTo[x].indexOf(':') + 1))}`
		}
	}

	if (typeof window.finalRedirect !== 'undefined' && window.finalRedirect.length !== 0) {
		redirect = encodeURIComponent(window.finalRedirect[window.finalRedirect.length - 1])
	}

	let triggerIntegration
	if (typeof window.triggerIntegration !== 'undefined') {
		triggerIntegration = encodeURIComponent(JSON.stringify(window.triggerIntegration))
	}
	let data = `${formData}&id=${form.attr('data-id')}&location=${encodeURIComponent(window.location.href)}&emails=${emails}&hidden=${hidden}&redirect=${redirect}&type=${type}&triggerIntegration=${triggerIntegration}`

	let abort = { abort: false }
	if (type === 'all') {
		form.find('.validation-lenient, .validation-strict').each(function() {
			if (!jQuery(this).parents('.form-element').hasClass('state-hidden')) {
				let a = jQuery(this).fcValidate()
				if (a === false) {
					abort.abort = true
				}
			}
		})
	} else {
		let pageValidate = type - 1
		form.find(`.form-page-${pageValidate} .validation-lenient, .validation-strict`).each(function() {
			if (!jQuery(this).parents('.form-element').hasClass('state-hidden') && jQuery(this).parents(`.form-page-${pageValidate}`).length !== 0) {
				let a = jQuery(this).fcValidate()
				if (a === false) {
					abort.abort = true
				}
			}
		})
	}
	if (type === 'all') {
		jQuery(document).trigger('formcraft_submit_trigger', [form, data, abort])
	}
	if (abort.abort === true) {
		if (form.find('.error-field').length === 0) {
			return false
		}
		if (helpers.isElementInViewport(form.find('.error-field').first()) === false) {
			let y = form.find('.error-field').first().offset().top
			if (form.parents('.fc-form-modal').length) {
				y = (form.parents('.fc-form-modal').scrollTop() + y) - (form.height() + 130)
				form.parents('.fc-form-modal').animate({ scrollTop: form.find('.error-field').first().position().top }, 600)
			} else if (form.parents('.fc-sticky').length) {
				jQuery('.fc-sticky').animate({ scrollTop: form.find('.error-field').first().position().top - 30 }, 600)
			} else if (form.parent().find('.fc-pagination.fixed').length) {
				jQuery('html, body').animate({ scrollTop: y - 200 }, 600)
			} else {
				jQuery('html, body').animate({ scrollTop: y - 120 }, 600)
			}
		}
		if (typeof callback !== 'undefined') {
			callback(false)
		}
		return false
	}
	form.find('.submit-response').slideUp('fast').html()
	form.find('.submit-cover').addClass('disabled')
	form.find('.form-element').removeClass('error-field')
	if (type === 'all') {
		form.find('.submit-button').attr('disabled', true)
	}
	let tempForm = form
	jQuery.ajax({
		url: FC.ajaxurl,
		type: 'POST',
		timeout: 120000,
		data: `action=formcraft3_form_submit&${data}`,
		dataType: 'json'
	})
	.done(function(response) {
		form = tempForm
		if (response.debug) {
			if (response.debug.failed) {
				if (showDebug === true) {
					for (let x in response.debug.failed) {
						globalNotification('error', response.debug.failed[x])
					}
				}
			}
			if (response.debug.success) {
				if (showDebug === true) {
					for (let x in response.debug.success) {
						globalNotification('success', `<i class='formcraft-icon'>check</i> ${response.debug.success[x]}`)
					}
				}
			}
		}
		if (response.failed) {
			if (form.parents('.fc-form-modal').length !== 0) {
				setTimeout(function() {
					form.addClass('shake')
				}, 600)
				setTimeout(function() {
					form.removeClass('shake')
				}, 1100)
			}
			form.find('.validation-lenient').addClass('validation-strict').removeClass('.validation-lenient')
			form.find('.submit-response').html(`<span class="has-error">${response.failed}</span>`).slideDown('fast')
			if (response.errors) {
				for (let field in response.errors) {
					form.find(`.form-element-${field}`).addClass('error-field')
					form.find(`.form-element-${field} .error`).text(response.errors[field])
				}
			}
			if (form.find('.error-field').length !== 0) {
				if (helpers.isElementInViewport(form.find('.error-field').first()) === false) {
					let y = form.find('.error-field').first().offset().top
					if (form.parents('.fc-form-modal').length) {
						y = (form.parents('.fc-form-modal').scrollTop() + y) - (form.height() + 130)
						form.parents('.fc-form-modal').animate({ scrollTop: form.find('.error-field').first().position().top }, 600)
					} else if (form.parents('.fc-sticky').length) {
						jQuery('.fc-sticky').animate({ scrollTop: form.find('.error-field').first().position().top - 30 }, 600)
					} else if (form.parent().find('.fc-pagination.fixed').length) {
						jQuery('html, body').animate({ scrollTop: y - 200 }, 600)
					} else {
						jQuery('html, body').animate({ scrollTop: y - 120 }, 600)
					}
				}
			}
		} else if (typeof response.success !== 'undefined') {
			form.append('<div class="final-success"><i class="final-success-check formcraft-icon">check</i><span></span></div>')
			form.find('.final-success > span').html(response.success)
			form.addClass('submitted')
			form.find('.final-success').slideDown(800, function() {
			})
			form.find('.form-page').slideUp(800, function() {
				form.find('.form-element').remove()
			})
			if (form.parents('.fc-form-modal').length === 0 && form.parents('.fc-sticky').length === 0) {
				jQuery('html, body').animate({ scrollTop: form.offset().top - 100 }, 800)
			}
			jQuery(document).trigger('formcraft_submit_result', [form, response])
			if (response.redirect) {
				let delay = parseInt(form.attr('data-delay'), 10)
				delay = isNaN(delay) ? 2 : delay
				delay = Math.max(0, delay)
				setTimeout(function() {
					window.location.assign(response.redirect)
				}, delay * 1000)
			}
		}
		if (typeof callback !== 'undefined') {
			callback(response, form)
		}
	})
	.fail(function() {
		jQuery(element).find('.response').text('Connection error')
		if (typeof callback !== 'undefined') {
			callback(false)
		}
	})
	.always(function(response) {
		jQuery(document).trigger('formcraft_submit_success_trigger', [form, response])
		form.find('.submit-cover').addClass('enabled')
		form.find('.submit-cover').removeClass('disabled')
		if (type === 'all') {
			form.find('.submit-button').removeAttr('disabled')
		}
	})
}

jQuery(document).ready(function() {

	if (helpers.isMobile() === true) {
		jQuery('.email-cover input[type="text"]').prop('type', 'email')
	}

	if (jQuery('#fc-form-preview').length === 1) {
		jQuery('body').addClass('formcraft-css')
	}

	jQuery('body').on('click', '.fc-trigger-close', function() {
		jQuery('.fc-sticky').each(function() {
			if (jQuery(this).hasClass('show')) {
				jQuery(this).parent().find('[data-toggle="fc-sticky"]').trigger('click')
			}
		})
	})

	jQuery('.form-element.default-true').hide()
	jQuery('.fc-form').removeClass('fc-temp-class')
	jQuery('.fc-form .form-element.default-true').addClass('state-hidden')
	jQuery('body').on('click', '.field-cover div [class^="icon-"]', function() {
		jQuery(this).parent().find('input').focus()
	})
	jQuery('[href]').each(function() {
		let href = jQuery(this).attr('href')
		if (href.indexOf('form-view/') !== -1) {
			let sub = href.split('form-view/')
			if (jQuery(`.fc-form-modal .fc-form[data-id="${sub[sub.length - 1]}"]`).length) {
				let form = jQuery(`.fc-form-modal .fc-form[data-id="${sub[sub.length - 1]}"]`).first()
				let uniq = form.parents('.fc-form-modal').attr('id')
				jQuery(this).removeAttr('href')
				jQuery(this).attr('data-toggle', 'fc_modal')
				jQuery(this).attr('data-target', `#${uniq}`)
			}
		}
	})
	jQuery('.fc-form-modal .form-live').each(function() {
		if (jQuery(this).attr('data-bind') !== '') {
			let uniq = jQuery(this).attr('data-uniq')
			jQuery(jQuery(this).attr('data-bind')).each(function() {
				jQuery(this).attr('data-toggle', 'fc_modal')
				jQuery(this).attr('data-target', `#modal-${uniq}`)
			})
		}
	})
	jQuery('.fc-form').each(function() {
		let form = jQuery(this)
		jQuery(document).trigger('formcraft_math_change', [form])
	})

	jQuery('body').on('focus', '.password-cover input[type="password"], .address-cover input[type="text"] ,.oneLineText-cover input[type="text"],.datepicker-cover input[type="text"],.email-cover input[type="text"],.email-cover input[type="email"],.textarea-cover textarea,.dropdown-cover select,.matrix-cover input,.star-cover input,.thumb-cover input', function() {
		jQuery(this).parents('.field-cover').addClass('has-focus')
	})
	jQuery('body').on('blur', '.password-cover input[type="password"], .address-cover input[type="text"] ,.oneLineText-cover input[type="text"],.datepicker-cover input[type="text"],.email-cover input[type="text"],.email-cover input[type="email"],.textarea-cover textarea,.dropdown-cover select,.matrix-cover input,.star-cover input,.thumb-cover input', function() {
		jQuery(this).parents('.field-cover').removeClass('has-focus')
	})

	jQuery('body').on('change', '.dropdown-cover select', function() {
		if (jQuery(this).find('option:checked').length > 0 && jQuery(this).find('option:checked').text() !== '') {
			jQuery(this).parents('.field-cover').addClass('has-input')
		} else {
			jQuery(this).parents('.field-cover').removeClass('has-input')
		}
	})
	jQuery('body').on('input', '.address-cover input[type="text"], .oneLineText-cover input[type="text"],.password-cover input[type="password"],.datepicker-cover input[type="text"],.email-cover input[type="text"],.email-cover input[type="email"], .textarea-cover textarea', function() {
		if (jQuery(this).val().length > 0 || (typeof jQuery(this).attr('placeholder') !== 'undefined' && jQuery(this).attr('placeholder').length > 0)) {
			jQuery(this).parents('.field-cover').addClass('has-input')
		} else {
			jQuery(this).parents('.field-cover').removeClass('has-input')
		}
	})

	jQuery('.oneLineText-cover input[type="text"],.datepicker-cover input[type="text"], .email-cover input[type="text"], .email-cover input[type="email"], .textarea-cover textarea').trigger('input')
	jQuery('.customText-cover input[type="hidden"],.timepicker-cover input[type="hidden"],.slider-cover input[type="hidden"],.fileupload-cover input[type="hidden"],.checkbox-cover input[type="radio"],.star-cover input[type="radio"],.thumb-cover input[type="radio"],.checkbox-cover input[type="checkbox"],.dropdown-cover select').trigger('change')

	setTimeout(function() {
		jQuery('.time-fields-cover > select').first().trigger('change')
	}, 500)
	jQuery('.fc-pagination').each(function() {
		jQuery(this).find('.pagination-trigger').eq(0).addClass('active')
	})
	jQuery('.fc-form .form-page-0').addClass('active')
	jQuery('body').on('change', '.checkbox-cover label input,.update-label label input', function() {
		if (jQuery(this).is(':checked')) {
			let name = jQuery(this).attr('name')
			jQuery(`[name="${name}"]`).parent().removeClass('active')
			jQuery(this).parent().addClass('active')
		}
	})
	if (helpers.isiOS()) {
		jQuery('body').on('touchstart', '.star-cover label, .thumb-cover label', function() {
			event.preventDefault()
			jQuery(this).trigger('click')
		})
		jQuery('body').on('touchstart', '[data-toggle="fc_modal"]', function(event) {
			event.preventDefault()
			jQuery(this).trigger('click')
		})
		jQuery('body').on('touchstart', '[data-toggle="fc-sticky"]', function() {
			event.preventDefault()
			jQuery(this).trigger('click')
		})
	}
	jQuery('body').on('change', '.star-cover label input', function() {
		if (jQuery(this).is(':checked')) {
			let name = jQuery(this).attr('name')
			jQuery(`[name="${name}"]`).parent().removeClass('active')
			jQuery(this).parent().addClass('active')
			let index = jQuery(this).parent().index()
			jQuery(this).parent().parent().find('label').removeClass('fake-click')
			jQuery(this).parent().parent().find('label').slice(0, index + 1).addClass('fake-click')
		}
	})
	jQuery('.update-label label.active').removeClass('active')
	jQuery('.powered-by').each(function() {
		let width = jQuery(this).parent().find('.fc-form').outerWidth()
		jQuery(this).css('width', `${width} px`)
	})
	setTimeout(function() {
		jQuery('.fc-form-modal').appendTo('body')
	}, 500)
	jQuery('.formcraft-css.placement-right').appendTo('body')
	jQuery('.formcraft-css.placement-left').appendTo('body')
	jQuery('.body-append').appendTo('body')
	setTimeout(function() {
		jQuery('.image_button_cover a').each(function() {
			let height = (parseInt(jQuery(this).outerWidth(), 10) / 2) + jQuery(this).outerHeight()
			jQuery(this).css('top', `-${height}px`)
		})
	}, 100)
	setTimeout(function() {
		jQuery('.image_button_cover a').each(function() {
			jQuery(this).parents('.image_button_cover').addClass('now-show')
		})
	}, 400)
	jQuery('body').on('click', '[data-toggle="fc-sticky"]', function() {
		let element = jQuery(jQuery(this).attr('data-target'))
		let elementButton = jQuery(jQuery(this).attr('data-target')).parent().find('.fc-sticky-button')
		if (element.hasClass('show')) {
			element.addClass('hiding')
			elementButton.addClass('showing')
			setTimeout(function() {
				element.removeClass('show hiding')
				elementButton.removeClass('hide showing')
			}, 400)
		} else {
			let form = element.find('.fc-form').attr('data-id')
			jQuery.get(`${FC.ajaxurl}?action=formcraft3_trigger_view&id=${form}`)
			element.addClass('show')
			elementButton.addClass('hide')
		}
	})
	jQuery(document).keyup(function(e) {
		jQuery('.fc-sticky').each(function() {
			if (jQuery(this).hasClass('show') && e.which === 27) {
				jQuery(this).parent().find('[data-toggle="fc-sticky"]').trigger('click')
			}
		})
	})
	let bodyHeight = parseInt(jQuery(window).height(), 10) * 0.8
	jQuery('.fc-sticky').css('max-height', `${bodyHeight}px`)
	jQuery(document).mouseup(function (e) {
		let container1 = jQuery('.fc-sticky')
		let container2 = jQuery('.fc-datepicker')
		let container3 = jQuery('.fc-sticky-button')
		if (!container1.is(e.target) && container1.has(e.target).length === 0 && !container2.is(e.target) && container2.has(e.target).length === 0 && !container3.is(e.target)) {
			jQuery('.fc-sticky').each(function() {
				if (jQuery(this).hasClass('show')) {
					jQuery(this).parent().find('[data-toggle="fc-sticky"]').trigger('click')
				}
			})
		}
	})
	setTimeout(function() {
		jQuery('.fc-sticky').each(function() {
			if (jQuery(this).hasClass('fc-sticky-right') || jQuery(this).hasClass('fc-sticky-left')) {
				let height = jQuery(this).find('.fc-form').height()
				height = Math.min(bodyHeight, height)
				jQuery(this).css('margin-top', `-${(height / 2)}px`)
				jQuery(this).find('.fc-form').addClass('calculated')
			}
		})
	}, 500)

	jQuery('.fc-form-modal').each(function() {
		if (jQuery(this).attr('data-auto') && !isNaN(parseFloat(jQuery(this).attr('data-auto')))) {
			let modal = jQuery(this)
			setTimeout(function() {
				modal.fc_modal('show')
			}, parseFloat(jQuery(this).attr('data-auto')) * 1000)
		}
		if (jQuery(this).find('.pagination-trigger').length > 1) {
			let height = jQuery(this).find('.fc_close').parents('.fc_modal-dialog').find('.fc-pagination-cover').height()
			let width = jQuery(this).find('.fc_close').parents('.fc_modal-dialog').find('.fc-form').width()
			jQuery(this).find('.fc_close').css({
				'margin-top': height,
				left: '50%',
				'margin-left': ((width / 2) - 30)
			})
		}
	})
	jQuery('.fc-sticky').each(function() {
		if (jQuery(this).attr('data-auto') && !isNaN(parseFloat(jQuery(this).attr('data-auto')))) {
			let modal = jQuery(this)
			setTimeout(function() {
				if (!modal.hasClass('show')) {
					modal.parent().find('.fc-sticky-button').trigger('click')
				}
			}, parseFloat(jQuery(this).attr('data-auto')) * 1000)
		}
	})
	jQuery('.star-cover label').hover(function() {
		let index = jQuery(this).index('label')
		jQuery(this).parent().find('label').slice(0, index + 1 - jQuery(this).prevAll('.formcraft-icon').length).addClass('fake-hover')
		jQuery(this).parent().find('label').slice(index + 1 - jQuery(this).prevAll('.formcraft-icon').length, jQuery(this).parent().find('label').length).addClass('fake-empty')
	}, function() {
		jQuery(this).parent().find('label').removeClass('fake-hover fake-empty')
	})
	if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
		jQuery('.datepicker-cover input[type="text"]').attr('readonly', 'readonly')
	}
	setTimeout(function() {
		jQuery('body').on('blur change', '.fc-form .validation-lenient', function(e) {
			if (jQuery(this).fcValidate() === false) {
				jQuery(this).addClass('validation-strict').removeClass('validation-lenient')
			}
		})
	}, 1000)
	jQuery('body').on('keyup change input', '.fc-form .validation-strict', function() {
		if (jQuery(this).fcValidate() === false) {
			jQuery(this).addClass('validation-strict').removeClass('validation-lenient')
		} else {
			jQuery(this).addClass('validation-lenient').removeClass('validation-strict')
		}
	})
})
