(function( $ ) {

	/**
	 * JavaScript class for working with third party services.
	 *
	 * @since 1.5.4
	 */
	var FLBuilderServices = {

		/**
		 * Initializes the services logic.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		init: function()
		{
			var body = $('body', window.parent.document);

			// Standard Events
			body.on( 'change', '.fl-builder-service-select', this._serviceChange );
			body.on( 'click', '.fl-builder-service-connect-button', this._connectClicked );
			body.on( 'change', '.fl-builder-service-account-select', this._accountChange );
			body.on( 'click', '.fl-builder-service-account-delete', this._accountDeleteClicked );

			// Campaign Monitor Events
			body.on( 'change', '.fl-builder-campaign-monitor-client-select', this._campaignMonitorClientChange );

			// MailChimp Events
			body.on( 'change', '.fl-builder-mailchimp-list-select', this._mailChimpListChange );

			// ActiveCampaign Events
			body.on( 'change', '.fl-builder-activecampaign-list_type-select', this._activeCampaignChange );
		},

		/**
		 * Show the lightbox loading graphic and remove errors.
		 *
		 * @param {Object} ele An element within the lightbox.
		 * @return void
		 * @since 1.5.4
		 */
		_startSettingsLoading: function( ele )
		{
			var lightbox    = $( '.fl-builder-settings', window.parent.document ),
				wrap        = ele.closest( '.fl-builder-service-settings', window.parent.document ),
				error       = $( '.fl-builder-service-error', window.parent.document );

			lightbox.append( '<div class="fl-builder-loading"></div>' );
			wrap.addClass( 'fl-builder-service-settings-loading' );
			error.remove();
		},

		/**
		 * Remove the lightbox loading graphic.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_finishSettingsLoading: function()
		{
			var lightbox    = $( '.fl-builder-settings', window.parent.document ),
				wrap        = $( '.fl-builder-service-settings-loading', window.parent.document );

			lightbox.find( '.fl-builder-loading' ).remove();
			wrap.removeClass( 'fl-builder-service-settings-loading' );
		},

		/**
		 * Fires when the service select changes.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_serviceChange: function()
		{
			var nodeId      = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				select      = $( this ),
				selectRow   = select.closest( 'tr' ),
				service     = select.val();

			const dynamicOptions = {
				global          : FLBuilderSettingsForms.config.global, 
				dynamicEditing  : FLBuilderSettingsForms.config.dynamicEditing, 
				rootNodeEditing : FLBuilderSettingsForms.config.rootNodeEditing,
			};
			
			selectRow.siblings( 'tr.fl-builder-service-account-row' ).remove();
			selectRow.siblings( 'tr.fl-builder-service-connect-row' ).remove();
			selectRow.siblings( 'tr.fl-builder-service-field-row' ).remove();
			$( '.fl-builder-service-error', window.parent.document ).remove();

			if ( '' === service ) {
				return;
			}

			FLBuilderServices._startSettingsLoading( select );

			FLBuilder.ajax( {
				action  : 'render_service_settings',
				node_id : nodeId,
				service : service,
				dynamic_options : dynamicOptions,
			}, FLBuilderServices._serviceChangeComplete );
		},

		/**
		 * AJAX callback for when the service select changes.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.5.4
		 */
		_serviceChangeComplete: function( response )
		{
			var data        = FLBuilder._jsonParse( response ),
				wrap        = $( '.fl-builder-service-settings-loading', window.parent.document ),
				selectRow   = wrap.find( '.fl-builder-service-select-row' );

			selectRow.after( data.html );
			FLBuilderServices._addAccountDelete( wrap );
			FLBuilderServices._finishSettingsLoading();
		},

		/**
		 * Fires when the service connect button is clicked.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_connectClicked: function()
		{
			var nodeId          = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				wrap            = $( this ).closest( '.fl-builder-service-settings' ),
				select          = wrap.find( '.fl-builder-service-select' ),
				connectRows     = wrap.find( '.fl-builder-service-connect-row' ),
				connectInputs   = wrap.find( '.fl-builder-service-connect-input' ),
				input           = null,
				name            = null,
				i               = 0,
				data            = {
					action          : 'connect_service',
					node_id         : nodeId,
					service         : select.val(),
					fields          : {},
					dynamic_options : {
						global          : FLBuilderSettingsForms.config.global, 
						dynamicEditing  : FLBuilderSettingsForms.config.dynamicEditing, 
						rootNodeEditing : FLBuilderSettingsForms.config.rootNodeEditing,
					},
				};

			for ( ; i < connectInputs.length; i++ ) {
				input                   = connectInputs.eq( i );
				name                    = input.attr( 'name' );
				data.fields[ name ]  = input.val();
			}

			connectRows.hide();
			FLBuilderServices._startSettingsLoading( select );
			FLBuilder.ajax( data, FLBuilderServices._connectComplete );
		},

		/**
		 * AJAX callback for when the service connect button is clicked.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.5.4
		 */
		_connectComplete: function( response )
		{
			var data        = FLBuilder._jsonParse( response ),
				wrap        = $( '.fl-builder-service-settings-loading', window.parent.document ),
				selectRow   = wrap.find( '.fl-builder-service-select-row' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				accountRow  = wrap.find( '.fl-builder-service-account-row' ),
				account     = wrap.find( '.fl-builder-service-account-select' ),
				connectRows = wrap.find( '.fl-builder-service-connect-row' );

			if ( data.error ) {

				connectRows.show();

				if ( 0 === account.length ) {
					select.after( '<div class="fl-builder-service-error">' + data.error + '</div>' );
				}
				else {
					account.after( '<div class="fl-builder-service-error">' + data.error + '</div>' );
				}
			}
			else {
				connectRows.remove();
				accountRow.remove();
				selectRow.after( data.html );
			}

			FLBuilderServices._addAccountDelete( wrap );
			FLBuilderServices._finishSettingsLoading();
		},

		/**
		 * Fires when the service account select changes.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_accountChange: function()
		{
			var nodeId      = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				wrap        = $( this ).closest( '.fl-builder-service-settings' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				account     = wrap.find( '.fl-builder-service-account-select' ),
				connectRows = wrap.find( '.fl-builder-service-connect-row' ),
				fieldRows   = wrap.find( 'tr.fl-builder-service-field-row' ),
				error       = $( '.fl-builder-service-error', window.parent.document ),
				value       = account.val(),
				data        = null;

			const dynamicOptions = {
				global          : FLBuilderSettingsForms.config.global, 
				dynamicEditing  : FLBuilderSettingsForms.config.dynamicEditing, 
				rootNodeEditing : FLBuilderSettingsForms.config.rootNodeEditing,
			};
			
			connectRows.remove();
			fieldRows.remove();
			error.remove();

			if ( 'add_new_account' == value ) {
				data = {
					action  : 'render_service_settings',
					node_id : nodeId,
					service : select.val(),
					add_new : true,
					dynamic_options : dynamicOptions,
				};
			}
			else if ( '' !== value ) {
				data = {
					action  : 'render_service_fields',
					node_id : nodeId,
					service : select.val(),
					account : value,
					dynamic_options : dynamicOptions,
				};
			}

			if ( data ) {
				FLBuilderServices._startSettingsLoading( select );
				FLBuilder.ajax( data, FLBuilderServices._accountChangeComplete );
			}

			FLBuilderServices._addAccountDelete( wrap );
		},

		/**
		 * AJAX callback for when the service account select changes.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.5.4
		 */
		_accountChangeComplete: function( response )
		{
			var data        = FLBuilder._jsonParse( response ),
				wrap        = $( '.fl-builder-service-settings-loading', window.parent.document ),
				accountRow  = wrap.find( '.fl-builder-service-account-row' );

			accountRow.after( data.html );
			FLBuilderServices._finishSettingsLoading();
		},

		/**
		 * Adds an account delete link.
		 *
		 * @param {Object} wrap An element within the lightbox.
		 * @return void
		 * @since 1.5.4
		 */
		_addAccountDelete: function( wrap )
		{
			var account = wrap.find( '.fl-builder-service-account-select' );

			if ( account.length > 0 ) {

				wrap.find( '.fl-builder-service-account-delete' ).remove();

				if ( '' !== account.val() && 'add_new_account' != account.val() ) {
					account.after( '<a href="javascript:void(0);" class="fl-builder-service-account-delete">' + FLBuilderStrings.deleteAccount + '</a>' );
				}
			}
		},

		/**
		 * Fires when the account delete link is clicked.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_accountDeleteClicked: function()
		{
			var wrap        = $( this ).closest( '.fl-builder-service-settings' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				account     = wrap.find( '.fl-builder-service-account-select' );

			if ( confirm( FLBuilderStrings.deleteAccountWarning ) ) {

				FLBuilder.ajax( {
					action  : 'delete_service_account',
					service : select.val(),
					account : account.val()
				}, FLBuilderServices._accountDeleteComplete );

				FLBuilderServices._startSettingsLoading( account );
			}
		},

		/**
		 * AJAX callback for when the account delete link is clicked.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_accountDeleteComplete: function()
		{
			var wrap   = $( '.fl-builder-service-settings-loading', window.parent.document ),
				select = wrap.find( '.fl-builder-service-select' );

			FLBuilderServices._finishSettingsLoading();

			select.trigger( 'change' );
		},

		/* Campaign Monitor
		----------------------------------------------------------*/

		/**
		 * Fires when the Campaign Monitor client select is changed.
		 *
		 * @return void
		 * @since 1.5.4
		 */
		_campaignMonitorClientChange: function()
		{
			var nodeId      = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				wrap        = $( this ).closest( '.fl-builder-service-settings' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				account     = wrap.find( '.fl-builder-service-account-select' ),
				client      = $( this ),
				list        = wrap.find( '.fl-builder-service-list-select' ),
				value       = client.val();

			if ( 0 !== list.length ) {
				list.closest( 'tr' ).remove();
			}
			if ( '' === value ) {
				return;
			}

			FLBuilderServices._startSettingsLoading( select );

			FLBuilder.ajax( {
				action  : 'render_service_fields',
				node_id : nodeId,
				service : select.val(),
				account : account.val(),
				client  : value
			}, FLBuilderServices._campaignMonitorClientChangeComplete );
		},

		/**
		 * AJAX callback for when the Campaign Monitor client select is changed.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.5.4
		 */
		_campaignMonitorClientChangeComplete: function( response )
		{
			var data    = FLBuilder._jsonParse( response ),
				wrap    = $( '.fl-builder-service-settings-loading', window.parent.document ),
				client  = wrap.find( '.fl-builder-campaign-monitor-client-select' );

			client.closest( 'tr' ).after( data.html );
			FLBuilderServices._finishSettingsLoading();
		},

		/* MailChimp
		----------------------------------------------------------*/

		/**
		 * Fires when the MailChimp list select is changed.
		 *
		 * @return void
		 * @since 1.6.0
		 */
		_mailChimpListChange: function()
		{
			var nodeId      = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				wrap        = $( this ).closest( '.fl-builder-service-settings' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				account     = wrap.find( '.fl-builder-service-account-select' ),
				list        = wrap.find( '.fl-builder-service-list-select' );

			$( '.fl-builder-mailchimp-group-select', window.parent.document ).closest( 'tr' ).remove();

			if ( '' === list.val() ) {
				return;
			}

			FLBuilderServices._startSettingsLoading( select );

			FLBuilder.ajax( {
				action  : 'render_service_fields',
				node_id : nodeId,
				service : select.val(),
				account : account.val(),
				list_id : list.val()
			}, FLBuilderServices._mailChimpListChangeComplete );
		},

		/**
		 * AJAX callback for when the MailChimp list select is changed.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.6.0
		 */
		_mailChimpListChangeComplete: function( response )
		{
			var data    = FLBuilder._jsonParse( response ),
				wrap    = $( '.fl-builder-service-settings-loading', window.parent.document ),
				list    = wrap.find( '.fl-builder-service-list-select' );

			list.closest( 'tr' ).after( data.html );
			FLBuilderServices._finishSettingsLoading();
		},

		/* ActiveCampaign
		----------------------------------------------------------*/

		/**
		 * Fires when the ActiveCampaign list type select is changed.
		 *
		 * @return void
		 * @since 1.6.0
		 */
		_activeCampaignChange: function()
		{
			var nodeId      = $( '.fl-builder-settings', window.parent.document ).data( 'node' ),
				wrap        = $( this ).closest( '.fl-builder-service-settings' ),
				select      = wrap.find( '.fl-builder-service-select' ),
				account     = wrap.find( '.fl-builder-service-account-select' ),
				list    	= wrap.find( '.fl-builder-service-list-select' );
				list_type   = wrap.find( 'select[name="list_type"]' );

			if ( 0 !== list.length ) {
				list.closest( 'tr' ).remove();
			}

			if ( '' === list_type.val() ) {
				return;
			}

			FLBuilderServices._startSettingsLoading( select );

			FLBuilder.ajax( {
				action  : 'render_service_fields',
				node_id : nodeId,
				service : select.val(),
				account : account.val(),
				list_type : list_type.val()
			}, FLBuilderServices._activeCampaignTypeChangeComplete );
		},

		/**
		 * AJAX callback for when the ActiveCampaign list select is changed.
		 *
		 * @param {String} response The JSON response.
		 * @return void
		 * @since 1.6.0
		 */
		_activeCampaignTypeChangeComplete: function( response )
		{
			var data    	= FLBuilder._jsonParse( response ),
				wrap    	= $( '.fl-builder-service-settings-loading', window.parent.document ),
				fieldRow  	= wrap.find( '.fl-builder-service-field-row' );

			fieldRow.after( data.html );
			FLBuilderServices._finishSettingsLoading();
		}
	};

	$ ( function() {
		FLBuilderServices.init();
	});

})( jQuery );
