(function($) {

	window.onLoadPPReCaptcha = function () {
		var reCaptchaFields = $('.pp-grecaptcha'),
			widgetID;

		if (reCaptchaFields.length > 0) {
			reCaptchaFields.each(function (i) {
				var self = $(this),
					attrWidget = self.attr('data-widgetid'),
					newID = $(this).attr('id'); // + '-' + i;
				// Avoid re-rendering as it's throwing API error
				if ((typeof attrWidget !== typeof undefined && attrWidget !== false)) {
					return;
				}
				else {
					// Increment ID to avoid conflict with the same form.
					self.attr('id', newID);

					widgetID = grecaptcha.render(newID, {
						sitekey	: self.data('sitekey'),
						theme	: self.data('theme'),
						size	: self.data('validate'),
						callback: function (response) {
							if ( response != '' ) {
								self.attr('data-pp-grecaptcha-response', response);

								// Re-submitting the form after a successful invisible validation.
								if ('invisible' == self.data('validate')) {
									self.closest('.fl-module').find('.pp-submit-button').trigger('click');
								}
							}
						}
					});

					self.attr('data-widgetid', widgetID);
				}
			});
		}
	};

	PPRegistrationForm = function( settings ) {
		this.settings  	= settings;
		this.nodeClass 	= '.fl-node-' + settings.id;
		this.i18n  		= settings.i18n;
		this.messages  	= settings.i18n.messages;
		this.form    	= $( this.nodeClass ).find( '.pp-registration-form' );
		this.fields 	= {};
		this.errorCodes = {};

		this._init();
	};

	PPRegistrationForm.prototype = {

		settings	: {},
		nodeClass	: '',
		messages	: {},
		isValid		: true,
		fields		: {},
		errorCodes	: {},

		_init: function()
		{
			if ( this.form.length < 1 ) {
				return;
			}
			this._initFields();
			this._bindErrorCodes();
			this._bindEvents();
		},

		_initFields: function() {
			this.fields = {
				'user_login': this.form.find( '.pp-rf-field[data-field-type="user_login"]' ),
				'user_email': this.form.find( '.pp-rf-field[data-field-type="user_email"]' ),
				'user_pass': this.form.find( '.pp-rf-field[data-field-type="user_pass"]' ),
				'confirm_user_pass': this.form.find( '.pp-rf-field[data-field-type="confirm_user_pass"]' ),
				'user_url': this.form.find( '.pp-rf-field[data-field-type="user_url"]' ),
				'first_name': this.form.find( '.pp-rf-field[data-field-type="first_name"]' ),
				'last_name': this.form.find( '.pp-rf-field[data-field-type="last_name"]' ),
				'consent': this.form.find( '.pp-rf-field[data-field-type="consent"]' ),
				'recaptcha': this.form.find( '.pp-rf-field[data-field-type="recaptcha"]' ),
			};

			// Bind control.
			Object.keys( this.fields ).forEach( function( fieldName ) {
				if ( 'undefined' !== typeof fieldName ) {
					var field = this.fields[ fieldName ];
					var control = field.find( '.pp-rf-control[name="' + fieldName + '"]' );
					if ( control.length > 0 ) {
						this.fields[ fieldName ].control = control;
					}
				}
			}.bind( this ) );
		},

		_bindErrorCodes: function() {
			this.errorCodes = {
				'empty_email': 'user_email',
				'invalid_email': 'user_email',
				'email_exists': 'user_email',
				'username_wp_error': 'user_login',
				'invalid_username': 'user_login',
				'username_exists': 'user_login',
				'password': 'user_pass',
				'password_mismatch': 'confirm_user_pass',
				'invalid_url': 'user_url',
				'recaptcha_php_ver': 'recaptcha',
				'recaptcha_missing_key': 'recaptcha',
			};
		},

		_bindEvents: function() {
			if ( this.fields.user_pass.find( '.pp-rf-toggle-pw' ).length > 0 ) {
				this.fields.user_pass.find( '.pp-rf-toggle-pw' )
					.on( 'click', this._passwordToggle.bind( this ) );
			}

			if ( this.settings.pws_meter && 'undefined' !== typeof wp.passwordStrength ) {
				this.fields.user_pass.control.on( 'input', this._beginPwsMeter.bind( this ) );
			}

			$( this.nodeClass + ' .pp-button' ).on( 'click', this._submit.bind( this ) );
		},

		_getFieldByCode: function( code ) {
			if ( 'undefined' !== typeof this.errorCodes[ code ] ) {
				var fieldType = this.errorCodes[ code ];
				var field = this.fields[ fieldType ];

				return field;
			}

			return false;
		},

		_getFormData: function() {
			var formData = new FormData( $(this.nodeClass + ' .pp-registration-form')[0] );
			formData.append( 'referrer', location.toString() );

			return formData;
		},

		_passwordToggle: function() {
			var pwField = this.fields.user_pass;
			if ( 'text' === pwField.control.attr( 'type' ) ) {
				pwField.control.attr( 'type', 'password' );
				pwField.find( '.pp-rf-toggle-pw' )
					.attr( 'aria-label', this.i18n.pw_toggle_text.show )
					.find( 'span' )
					.removeClass( 'dashicons-hidden' )
					.addClass( 'dashicons-visibility' );
			} else {
				pwField.control.attr( 'type', 'text' );
				pwField.find( '.pp-rf-toggle-pw' )
					.attr( 'aria-label', this.i18n.pw_toggle_text.hide )
					.find( 'span' )
					.removeClass( 'dashicons-visibility' )
					.addClass( 'dashicons-hidden' );
			}
		},

		_beginPwsMeter: function(e) {
			var password1 	= $(e.target).val(),
				password2 	= false,
				pwsStatus 	= this.fields.user_pass.find( '.pp-rf-pws-status' ),
				blacklist	= wp.passwordStrength.userInputBlacklist();

			if ( this.fields.confirm_user_pass.length > 0 ) {
				//password2 = this.fields.confirm_user_pass.control.val();
			}

			pwsStatus.removeClass( 'short bad good strong' );

			// calculate the password strength.
			var pws = wp.passwordStrength.meter( password1, blacklist, password2 );
			
			switch ( pws ) {
				case 0:
					pwsStatus.addClass( 'short' ).html( pwsL10n.short );
					break;
				case 1:
					pwsStatus.addClass( 'bad' ).html( pwsL10n.bad );
					break;
				case 2:
				case 3:
					pwsStatus.addClass( 'good' ).html( pwsL10n.good );
					break;	
				case 4:
					pwsStatus.addClass( 'strong' ).html( pwsL10n.strong );
					break;
			}

			if ( '' === password1 ) {
				pwsStatus.removeClass( 'short bad good strong' ).html('');
			} else {
				this._removeErrorClass( this.fields.user_pass );
			}
		},

		_submit: function(e) {
			var theForm			= this.form,
				submit	  		= $(this.nodeClass + ' .pp-button'),
				formData		= this._getFormData(),
				reCaptchaField 	= $(this.nodeClass + ' .pp-grecaptcha'),
				reCaptchaValue 	= reCaptchaField.data('pp-grecaptcha-response'),
				ajaxurl	  		= bb_powerpack.getAjaxUrl(),
				email_regex 	= /\S+@\S+\.\S+/,
				postId      	= theForm.closest( '.fl-builder-content' ).data( 'post-id' ),
				templateId		= theForm.data( 'template-id' ),
				templateNodeId	= theForm.data( 'template-node-id' ),
				nodeId      	= theForm.closest( '.fl-module' ).data( 'node' ),
				isValid         = true;

			e.preventDefault();
			// End if button is disabled (sent already)
			if ( submit.hasClass( 'pp-disabled' ) ) {
				return;
			}

			theForm.find('.pp-rf-field').removeClass('pp-rf-field-error');

			// Validate Required.
			var self = this;
			theForm.find('.pp-rf-field.pp-rf-field-required').each(function() {
				var field    = $(this),
					name     = field.data( 'field-name' ),
					selector = $(this).find( '[name="' + name + '"]' );

				if ( selector.length > 0 ) {
					if ( 'checkbox' === selector.attr( 'type' ) || 'radio' === selector.attr( 'type' ) ) {
						if ( ! selector.is(':checked') ) {
							isValid = false;
							self._addErrorClass( field );
						} else if ( self._fieldHasError( field ) ) {
							self._removeErrorClass( field );
						}
					} else {
						if ( ! selector.val() || '' === selector.val() ) {
							isValid = false;
							self._addErrorClass( field );
						} else if ( self._fieldHasError( field ) ) {
							self._removeErrorClass( field );
						}
					}
				}
			});

			// Validate Email
			if ( this.fields.user_email.length > 0 ) {
				var email = this.fields.user_email.find('input[type="email"]'); 
				if ( email.val() === '' ) {
					isValid = false;
					this._addErrorClass( this.fields.user_email );
				} else if ( ! email_regex.test( email.val() ) ) {
					isValid = false;
					this._removeErrorClass( this.fields.user_email );
					this._addInlineError( this.fields.user_email, this.messages.error.invalid_email );
				} else if ( this._fieldHasError( this.fields.user_email ) ) {
					this._removeErrorClass( this.fields.user_email );
				}
			}

			// Validate password length.
			if ( this.fields.user_pass.length > 0 ) {
				var password = this.fields.user_pass.control;
				if ( '' !== password.val() && password.val().length < this.settings.min_pass_length ) {
					isValid = false;
					this._addInlineError( this.fields.user_pass, this.messages.error.password_length );
				}
			}

			// Validate confirm password.
			if ( this.fields.confirm_user_pass.length > 0 ) {
				var confirmPwd = this.fields.confirm_user_pass.find('input[name="confirm_user_pass"]').val();
				var password = this.fields.user_pass.find('input[name="user_pass"]').val();
				if ( '' !== confirmPwd && btoa( confirmPwd ) !== btoa( password ) ) {
					isValid = false;
					this._addInlineError( this.fields.confirm_user_pass, this.messages.error.password_mismatch );
				}
			}

			// validate reCAPTCHA
			if ( reCaptchaField.length > 0 && isValid ) {
				if ( 'undefined' === typeof reCaptchaValue || reCaptchaValue === false ) {
					if ( 'normal' == reCaptchaField.data( 'validate' ) ) {
						isValid = false;
						this._addErrorClass( this.fields.recaptcha );
					} else if ( 'invisible' == reCaptchaField.data( 'validate' ) ) {
						// Invoke the reCAPTCHA check.
						grecaptcha.execute( reCaptchaField.data( 'widgetid' ) );
					}
				} else {
					this._removeErrorClass( this.fields.recaptcha );
				}
			}

			if ( ! isValid ) {
				return;
			} else {

				// disable send button
				submit.addClass( 'pp-disabled' );

				if ( reCaptchaField.length > 0 ) {
					formData.append( 'recaptcha', true );
				}
				if ( reCaptchaValue ) {
					formData.append( 'recaptcha_response', reCaptchaValue );
				}

				if ( 'undefined' !== typeof templateId ) {
					formData.append( 'template_id', templateId );
					formData.append( 'template_node_id', templateNodeId );
				}
				formData.append( 'node_id', nodeId );
				formData.append( 'action', 'pp_register_user' );
				formData.append( 'security', theForm.data('nonce') );
				formData.append( 'post_id', postId );

				$.ajax( {
					url: ajaxurl,
					type: 'POST',
					dataType: 'json',
					data: formData,
					processData: false,
					contentType: false,
					success: this._submitComplete.bind( this ),
					error: this._onError,
				}, );
			}
		},

		_submitComplete: function( response ) {
			var noMessage 	= $( this.nodeClass + ' .pp-rf-success-none' );

			// On success show the success message
			if ( typeof response.success !== 'undefined' && response.success === true ) {
				$( this.nodeClass + ' .pp-rf-failed-error' ).fadeOut();
				if ( 'undefined' !== typeof response.data.redirect_url ) {
					window.location.href = response.data.redirect_url;
				} else if ( noMessage.length > 0 ) {
					noMessage.fadeIn();
				} else {
					$( this.nodeClass + ' .pp-registration-form' ).hide();
					$( this.nodeClass + ' .pp-after-submit-action.pp-success-custom-message' ).fadeIn();
				}
			} else { // On failure show fail message and re-enable the send button
				$(this.nodeClass).find( '.pp-button' ).removeClass('pp-disabled');
				if ( typeof response.data.message !== 'undefined' ) {
					var error = response.data;
					var field = this._getFieldByCode( error.code );
					var message = 'undefined' !== typeof this.messages.error[ error.code ] ? this.messages.error[ error.code ] : error.message;

					if ( field && field.length > 0 ) {
						this._addInlineError( field, message );
					} else {
						$(this.nodeClass + ' .pp-rf-failed-error').html( message );
						$(this.nodeClass + ' .pp-rf-failed-error').fadeIn();
					}
				} else {
					$(this.nodeClass + ' .pp-rf-failed-error').fadeIn();
				}
				return false;
			}
		},

		_onError: function( xhr, status ) {

		},

		_addInlineError: function( field, message ) {
			field.find('.pp-rf-error-inline').remove();
			field.addClass('pp-rf-field-error').append( '<span class="pp-rf-error-inline">' + message + '</span>' );
		},

		_addErrorClass: function( field ) {
			field.addClass( 'pp-rf-validation-error' );
		},

		_removeErrorClass: function( field ) {
			field.removeClass( 'pp-rf-validation-error' );
		},

		_fieldHasError: function( field ) {
			return field.hasClass( 'pp-rf-validation-error' );
		},

	};

})(jQuery);

