( function( blocksRegistry, element, data ) {
	const { registerPaymentMethod }						 = blocksRegistry;
	const { createElement, useEffect, useState, useRef } = element;
	const { useSelect }									 = data;

	let paymentMethodTitle = 'SplitIt';

	if ( 'undefined' !== typeof splititPaymentMethodData ) {
		paymentMethodTitle = splititPaymentMethodData.payment_method_title;
	}

	const SplitItPaymentMethod = ( props ) => {

		const isCreateAccountChecked = useSelect( ( select ) => {
			const store = select( 'wc/store/checkout' );
			if ( store ) {
				return store.getShouldCreateAccount();
			}
			return false;
		}, [] );

		const isShipToDifferentAddressChecked = useSelect( ( select ) => {
			const store = select( 'wc/store/checkout' );
			if ( store ) {
				return store.getUseShippingAsBilling();
			}
			return false;
		}, [] );

		const orderNotes = useSelect( ( select ) => {
			const store = select( 'wc/store/checkout' );
			if ( store ) {
				return store.getOrderNotes();
			}
			return '';
		}, [] );

		const [ isInitCalled, setIsInitCalled ]	 = useState( false );

		const isCreateAccountCheckedRef			 = useRef( isCreateAccountChecked );
		const isShipToDifferentAddressCheckedRef = useRef( isShipToDifferentAddressChecked );
		const orderNotesRef						 = useRef( orderNotes );
		const propsRef							 = useRef( props );

		useEffect( () => {
			isCreateAccountCheckedRef.current = isCreateAccountChecked;
		}, [ isCreateAccountChecked ] );

		useEffect( () => {
			isShipToDifferentAddressCheckedRef.current = isShipToDifferentAddressChecked;
		}, [ isShipToDifferentAddressChecked ] );

		useEffect( () => {
			orderNotesRef.current = orderNotes;
		}, [ orderNotes ] );

		useEffect( () => {
			propsRef.current = props;
		}, [ props ] );


		useEffect( () => {
			if ( ! isInitCalled && 'function' === typeof initSplitItPaymentBlocks ) {
				initSplitItPaymentBlocks(
					propsRef.current,
					isCreateAccountCheckedRef.current,
					isShipToDifferentAddressCheckedRef.current,
					orderNotesRef.current
				);
				setIsInitCalled( true );
			}
		}, [ props, isCreateAccountChecked, isShipToDifferentAddressChecked, orderNotes, isInitCalled ] );

		const { eventRegistration, emitResponse } = props;
		const { onPaymentSetup }				  = eventRegistration;

		useEffect( () => {
			const unsubscribe = onPaymentSetup( async () => {

				performPaymentBlocks(
					propsRef.current,
					isCreateAccountCheckedRef.current,
					isShipToDifferentAddressCheckedRef.current,
					orderNotesRef.current
				);

				const timeout		 = 120000;
				const startTime		 = Date.now();
				let paymentSuccess	 = false;
				let paymentError	 = false;
				let checkoutFormData = null;

				while ( ! paymentSuccess && ! paymentError && Date.now() - startTime < timeout ) {
					await new Promise( resolve => setTimeout( resolve, 1000 ) );
					paymentSuccess	 = 'true' === localStorage.getItem( 'flex_fields_success' );
					paymentError	 = 'false' !== localStorage.getItem( 'flex_fields_error' );
					checkoutFormData = localStorage.getItem( 'checkout_form_data' );
				}

				if ( paymentSuccess ) {
					return {
						type: emitResponse.responseTypes.SUCCESS,
						meta: {
							paymentMethodData: {
								checkoutFormData,
							},
						},
					};
				}

				if ( paymentError ) {
					let paymentErrorMessage = localStorage.getItem( 'flex_fields_error' );
					localStorage.setItem( 'flex_fields_error', 'false' );
					return {
						type: emitResponse.responseTypes.ERROR,
						message: paymentErrorMessage,
					};
				}

				window.location.reload();
				return {
					type: emitResponse.responseTypes.ERROR,
					message: 'Please check your input',
				};
			} );
			// Unsubscribes when this component is unmounted.
			return () => {
				unsubscribe();
			};

		}, [
			emitResponse.responseTypes.ERROR,
			emitResponse.responseTypes.SUCCESS,
			onPaymentSetup,
		]);


		return createElement( 'div', { className: 'payment_method_splitit' },
			createElement( 'div', { id: 'flex-form' } )
		);
	};

	registerPaymentMethod( {
		name: 'splitit',
		label: paymentMethodTitle,
		ariaLabel: paymentMethodTitle,
		edit: createElement( SplitItPaymentMethod ),
		canMakePayment: () => true,
		content: createElement( SplitItPaymentMethod )
	} );
} )(
	wc.wcBlocksRegistry,
	wp.element,
	wp.data
);