/**
 * Script to handle payment options for Square.
 *
 * @since 1.7.5
 */

"use strict";

jQuery(function ($) {

	var $squareForms = $( "[data-gateway*='square']" );

	if ( 0 === $squareForms.length ) {
		return;
	}

	var square_payment = {
		/**
		* Initialization.
		*/
		init: function () {
			square_payment.ready();
		},
		/**
		* Document Ready
		*/
		ready: function () {
			$( window ).on( "load" , square_payment.loadSquareCreditCard );
		},
		/**
		* Load credit card
		*/
		loadSquareCreditCard : async function() {
			let formId 			= $squareForms.data( 'form-id' );
			let cardContainer 	= '#everest_forms_square_gateway_' + formId;
			const appId			= evf_square_payment_obj.app_id;
			const locationId 	= evf_square_payment_obj.location_id;

			const payments = window.Square.payments( appId, locationId );
			const card = await payments.card();

			async function initializeCard( payments ) {
				await card.attach( cardContainer );
				$( ".sq-card-message" ).hide();
				return card;
			}

			try {
				await initializeCard( payments );
			} catch ( e ) {

			}

			$( '#evf-form-' + formId ).on( 'everest_forms_frontend_payment_before_success_message', async function( e, xhrData = null ) {
				e.preventDefault();
				var array 				= new Uint32Array(1);
				const idempotencyKey 	= window.crypto.getRandomValues(array)[0];

				var paymentItems= square_payment.getPaymentItems( $( '#evf-form-' + formId ) );

				var totalAmount = 0;
				paymentItems.items.map( function( item ) {
					totalAmount += item.price * item.quantity;
				} );

				// Do not process the square if total amount is 0.
				if ( 0 === totalAmount ){
					$( '#evf-form-'+formId )[0].submit();
				}

				var paymentMethod = $( "#evf-form-" + formId ).find( ".everest-forms-gateway[data-gateway='square']" ).data('gateway');

				if( 'square' ===  paymentMethod ) {

					if( 'submit' === e.type ) {
						return;
					}

					var $mountedElement = $( '#everest_forms_square_gateway_' + formId );
					if ( 'none' === $mountedElement.closest( '.evf-field' ).css( 'display' ) ) {
						return;
					}

					var paymentDetails = {
                        data : $( '#evf-form-' + formId ).serializeArray(),
                        form_id : formId,
                        total : totalAmount
                    };
					await square_payment.handlePaymentMethodSubmission( e, card, idempotencyKey, paymentDetails, xhrData, formId, locationId );
				}
			})
		},
		handlePaymentMethodSubmission : async function( event, paymentMethod, idempotencyKey, data, xhrData, formId, locationId ) {
			event.preventDefault();
			try {
			  const token = await square_payment.tokenize( paymentMethod, formId );
			  await square_payment.createPayment( token, idempotencyKey, data, xhrData, locationId );
			} catch ( e ) {
				square_payment.removeEntryAfterCardDeclined( xhrData );
				$( '#card-errors' ).html( e.message ).show();
				$( '#evf-submit-' + formId ).attr( 'disabled', false ).html( 'Submit' );
			}
		},
		// Get payments items
		getPaymentItems : function ( $form ){
			var paymentItems = [];

			var $paymentQuantities = $( $form ).find( 'input.evf-payment-quantity:visible' );
			var paymentQuantities = [];

			$.each( $paymentQuantities, function( index, paymentQuantity ) {
				var id       = $( paymentQuantity ).attr( 'id' );
				var quantity = $( paymentQuantity ).val();
				var mapField = $( paymentQuantity ).data( 'map_field' );

				quantity = '' === quantity ? 1 : quantity;

				paymentQuantities[ mapField ] = {
					id: id,
					quantity: Number( quantity )
				};
			} );

			var coupon = $( $form ).find( '.everest-forms-coupons input' ),
				coupon_discount = coupon.attr( 'data-discount' ),
				is_percent = coupon.attr( 'data-discount_percent' ),
				coupon_map_field = coupon.attr( 'data-discount_map_field' )


			// Payment singles visible ones and hidden type one.
			var $singleItems = $( $form ).find( 'div.evf-field-payment-single' ).filter( function() {
				return $( this ).is(":not([style*='display: none'])") || $( this ).hasClass( 'evf-field-hidden' );
			} );
			var singleItems = $.map( $singleItems, function( singleItem ) {
				var id       = $( singleItem ).attr( 'data-field-id' );
				var label    = $( singleItem ).find( '.evf-field-label' ).text().trim();
				var quantity = ( undefined === paymentQuantities[ id ] ) ? 1 : paymentQuantities[ id ].quantity;
				var price    = $( singleItem ).find('input.evf-payment-price').val();

					if (typeof price === 'number') {
						price = '' === price ? 0 : String(price).replace(',', '.').match(/[\d|.]+/)[0];
					} else if (typeof price === 'string') {
						price    = '' === price ? 0 : price.replace(',', '.').match(/[\d|.]+/)[0];
					}

					price = '' === price ? 0 : price.replace(',', '.').match(/[\d|.]+/)[0];
					price = ( '1' === is_percent && id === coupon_map_field ) ? price * ( 100 - coupon_discount ) / 100 : price;

				return {
					label: label,
					price: Number( price ),
					quantity: Number( quantity )
				};
			} );

			paymentItems = paymentItems.concat( singleItems );

			// Get payment items for checkboxes and multiples payment fields.
			var $paymentPrices = $( $form ).find( "div.evf-field:not([style*='display: none']) input.evf-payment-price").filter( ':not(.evf-payment-quantity)' ).filter( ':checked' );
			var paymentPrices  = $.map( $paymentPrices, function( paymentPrice ) {
				var id       = $( paymentPrice ).parents( 'div.evf-field' ).first().attr( 'data-field-id' );
				var quantity = ( undefined === paymentQuantities[ id ] ) ?  1 : paymentQuantities[ id ].quantity;
				var price    = $( paymentPrice ).data( 'amount' );

				var $label   = $( paymentPrice ).siblings( '.everest-forms-field-label-inline' ).first();

				if ( ! $label.length ) {
					$label = $( paymentPrice ).siblings( '.everest-forms-image-choices-label' ).first();
				}

				if (typeof price === 'number') {
					price = '' === price ? 0 : String(price).replace(',', '.').match(/[\d|.]+/)[0];
				} else if (typeof price === 'string') {
					price    = '' === price ? 0 : String(price).replace(',', '').match(/[\d|.]+/)[0];
				}

				 price = ( '1' === is_percent && id === coupon_map_field ) ? price * ( 100 - coupon_discount ) / 100 : price;

				return {
					label: $label.text(),
					price: Number( price ),
					quantity: quantity
				};
			} );

			paymentItems = paymentItems.concat( paymentPrices );

			// Get payment items for payment slider.
			var $sliderItems = $( $form ).find( 'div.evf-field-range-slider' ).filter( function() {
				return $( this ).is(":not([style*='display: none'])") && $( this ).find('input.evf-payment-price').length > 0;
			} );
			var sliderItems = $.map( $sliderItems, function( sliderItem ) {
				var id       = $( sliderItem ).attr( 'data-field-id' );
				var label    = $( sliderItem ).find( '.evf-field-label' ).text().trim();
				var quantity = ( undefined === paymentQuantities[ id ] ) ? 1 : paymentQuantities[ id ].quantity;
				var price    = $( sliderItem ).find('input.evf-payment-price').val();
				if (typeof price === 'number') {
					price = '' === price ? 0 : String(price).replace(',', '.').match(/[\d|.]+/)[0];
				} else if (typeof price === 'string') {
					price    = '' === price ? 0 : price.replace(',', '.').match(/[\d|.]+/)[0];
				}

				price = ( '1' === is_percent && id === coupon_map_field ) ? price * ( 100 - coupon_discount ) / 100 : price;

				return {
				label: label,
				price: Number( price ),
				quantity: Number( quantity )
				};
			} );

			paymentItems = paymentItems.concat( sliderItems );

			if ( undefined !== coupon_discount && coupon_discount > 0 && ( undefined === coupon_map_field || '' === coupon_map_field ) ) {
				var total = 0,
					title = paymentItems.map( function( item ) {
						total += item.price * item.quantity;
						return item.label;
					} ),
					total_after_discount = 0;
				if ( '1' === is_percent ) {
					total_after_discount = total * ( 100 - coupon_discount ) / 100;
				} else {
					total_after_discount = total - coupon_discount;
				}

				paymentItems = [{
					label: title.join( ', ' ),
					price: Number( total_after_discount ),
					quantity: 1
				}];
			}

			var payment= {
				items: paymentItems
			};

			var $paymentTotal = $( $form ) .find( '.evf-field-payment-total' );
			if ( 0 !== $paymentTotal.length ) {
				var total = $paymentTotal.find( ':hidden' ).val().slice(1).trim().replace(',', '');
				payment[ 'total' ] = Number( total );
				}

			return payment;

	},
	createPayment : async function( token, idempotencyKey, data, xhrData, locationId ) {
		const payment_data = {
			location_id 	: locationId,
			source_id		: token,
			idempotency_key : idempotencyKey,
			action 			: 'everest_forms_square_payment_credit_card',
			payment_data	: data,
			security 		: evf_square_payment_obj.security
			};

			$.ajax({
				url : evf_square_payment_obj.ajax_url,
				method: 'POST',
				data : payment_data,
				success : function ( response ) {

					var $form = $( '#evf-form-' + xhrData.form_id );
					if( response.success ){
						var data_to_update = {
							action : 'evf_square_update_entry_square_payment_status',
							security : evf_square_payment_obj.security,
							entry_id : xhrData.entry_id,
							payment_data : response.data
						}

						$.ajax({
							url: evf_square_payment_obj.ajax_url,
							method : 'POST',
							data : data_to_update,
							success : function ( response ){
								$form.css( 'display', 'block' );
								var redirect_url = ( xhrData && xhrData.redirect_url ) ? xhrData.redirect_url : '';
								if ( redirect_url ) {
									window.location = redirect_url;
									return;
								}

								let pdf_download_message = '';
								let quiz_reporting = '';
								if(xhrData.form_id !== undefined && xhrData.entry_id !== undefined && xhrData.pdf_download == true){
									pdf_download_message = '<br><small><a href="/?page=evf-entries-pdf&form_id='+ xhrData.form_id+'&entry_id='+ xhrData.entry_id+'">' + xhrData.pdf_download_message + '</a></small>';
								}

								if( xhrData.quiz_result_shown == true){
									quiz_reporting = xhrData.quiz_reporting;
								}

								$form.html( '<div class="everest-forms-notice everest-forms-notice--success" role="alert">' + xhrData.message + pdf_download_message + '</div>' + quiz_reporting ).focus();
							}
						})

					} else {
						if( '0' === response ){
							return;
						}
						$form.html( '<div class="everest-forms-notice everest-forms-notice--error" role="alert">'+ response.data[0].detail  +'</div>' ).focus();
					}
				}
			});
		},
		tokenize : async function( paymentMethod, formId ) {
			const tokenResult = await paymentMethod.tokenize();
			if ( tokenResult.status === 'OK' ) {
				return tokenResult.token;
			} else {
				if ( tokenResult.errors ) {
					const errorMessage = tokenResult.errors[0].message;
					throw new Error( errorMessage );
				}
			}
		},
		//remove entries after credit card is declined
		removeEntryAfterCardDeclined : function( xhrData ){
			var all_data = {
				entry_id : xhrData.entry_id,
				form_id : xhrData.form_id,
				action : 'everest_forms_square_payment_delete_entry_after_failed'
			}
			$.ajax({
				url : evf_square_payment_obj.ajax_url,
				method: 'POST',
				data : all_data,
				success : function( response ){
					// do nothing
				}
			})
		}
   }

   square_payment.init();
});
