(function($){
	'use strict';

	var permission_dialog = jQuery("#cartbounty-pro-push-notification-permission");
	var backdrop = jQuery("#cartbounty-pro-push-notification-permission-backdrop");
	var timePeriod = cartbounty_pn.hours; //Time period in hours

	//Main function for running Push notification process
	async function startPushNotifications(){
		
		if(!checkBrowserFeatures()) return; //Exit in case browser does not support Push notifications

		var permission = Notification.permission;
		var currentTime = new Date().getTime();
		var last_time_displayed = localStorage.getItem('cartbounty_pro_pn_last_time');

		if(permission === 'granted'){ //If permission granted - registering service worker and save subscription if not done already
			saveSubscription();
		
		}else if(permission === 'denied'){ //If permission denied - try unsubscribing user and exit
			unsubscribeUser();
			return;

		}else{ //Default route - if permission has not been granted nor denied yet, try collecting it
			unsubscribeUser(); //Try unsubscribing user in case permission was previously granted

			if(cartEmpty()) return; //Exit if cart is empty

			if(currentTime - last_time_displayed > timePeriod * 60 * 60 * 1000){ // If the time has passed, clear the cookie
				localStorage.removeItem('cartbounty_pro_pn_last_time');
			}

			if(last_time_displayed != null && timePeriod != 0) return; //If permission request shown, time not passed since last request and test mode disabled

			if(permission_dialog.length){ //If soft ask enabled and present on page - display soft ask dialog
				permission_dialog.addClass('cartbounty-pro-visible');

				if(cartbounty_pn.backdrop){
					backdrop.css('opacity', '').addClass('cartbounty-pro-visible'); //Show backdrop
				}

			}else{ //If soft ask disabled - hard notification request
				requestNotificationPermission();
			}
		}
	}

	//Function checks if cart is empty
	function cartEmpty(){
		var result = true;
		var product_count = cartbounty_pn.product_count; //Products in the shopping cart

		if(localStorage.getItem('cartbounty_pro_product_count') !== null){
			product_count = localStorage.getItem('cartbounty_pro_product_count');
		}

		if(product_count > 0){ //If cart is empty
			result = false;
		};

		return result;
	}

	//Function for checking if browser supports Psuh API and Service Workers
	function checkBrowserFeatures(){
		var supports = true;

		if(!('serviceWorker' in navigator)){ //If browser does not support Service Worker
			supports = false;
		}

		if(!('PushManager' in window)){ //If browser does not support Push API
			supports = false;
		}

		return supports;
	}

	//Asking for user permission to allow notifications
	async function requestNotificationPermission(){
		const permission = await window.Notification.requestPermission(); //Values of permission can be granted, default or denied

		if(permission === 'granted'){ //If permissions granted - register service worker and save subscription
			saveSubscription();
			closePermissionDialog( false );

		}else if(permission === 'denied'){
			closePermissionDialog( false );

		}else{
			closePermissionDialog();
		}
	}

	//Function that registers Service Worker and saves subscription
	async function saveSubscription(){

		if(cartEmpty()) return; //Exit if cart is empty

		//Registering Service Worker
		const swRegistration = await navigator.serviceWorker.register(cartbounty_pn.js_location + 'cartbounty-pro-push-notification-service-worker-loader.js.php', {scope: cartbounty_pn.scope});
		var registration = await navigator.serviceWorker.getRegistration( cartbounty_pn.scope );
		const user = await registration.pushManager.getSubscription();

		if(!user || !localStorage.getItem('cartbounty_pro_pn_user_subscribed')){//If user not subscribed

			var subscription = await registration.pushManager.subscribe({
				userVisibleOnly: true,
				applicationServerKey: urlBase64ToUint8Array( cartbounty_pn.vapid_public_key )
			});

			const user = await registration.pushManager.getSubscription();
			const publicKey = user.getKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(user.getKey('p256dh')))) : '';
			const privateKey = user.getKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(user.getKey('auth')))) : '';
			pushSubscription(subscription, publicKey, privateKey); //Sending subscription to database
		}
	}

	//Function unsubscribes user from current abandoned cart and unregisters Service Worker
	async function unsubscribeUser(){

		if(localStorage.getItem('cartbounty_pro_pn_user_subscribed')){ //If user has already been registered and now the notification permission has been revoked	
			pushSubscription(false, false, false, 'remove');
			var registration = await navigator.serviceWorker.getRegistration( cartbounty_pn.scope );

			if (registration){ //If Service Worker found - unregistering service worker
				registration.unregister();
			}

			localStorage.removeItem('cartbounty_pro_pn_user_subscribed');
		}
	};

	//Function that saves or removes subscription from abandoned cart
	async function pushSubscription(subscription = false, publicKey = false, privateKey = false, action = 'save' ) {
		var endpoint = '';
		
		if(subscription){
			endpoint = subscription.endpoint; // Get the endpoint URL from the subscription object
		}

		var data = {
			action: 			action + '_notification_subscription',
			endpoint: 			endpoint,
			public_key: 		publicKey,
			private_key: 		privateKey,
			nonce: 				cartbounty_pn.nonce
		}

		jQuery.post(cartbounty_co.ajaxurl, data,
		function(response){ //If successful response

			if( response.success == true ){

				if(action == 'save'){ //If subscription successful
					localStorage.setItem('cartbounty_pro_pn_user_subscribed', true);

				}else if(action == 'remove'){ //If successful subscription removal
					localStorage.removeItem('cartbounty_pro_pn_user_subscribed');
				}
			}
		})
		.fail(function(response){ //In case Ajax request was unable to fire
			if(response.status == '404'){
				console.log('Ajax request unable to fire due to missing access to native WordPress file: ' + cartbounty_co.ajaxurl + '. Please check with your server administrator that mod_security is disabled and nothing else has been setup to restrict access to this file.');
			}
		});
	}

	//Function for closing Notification permission request dialog
	function closePermissionDialog( setLocalStorage = true ){
		var currentTime = new Date().getTime();

		if(permission_dialog.length){ //In case Soft ask enabled and present - close it
			permission_dialog.addClass('cartbounty-pro-fade-out');
			
			if(cartbounty_pn.backdrop){
				backdrop.addClass('cartbounty-pro-fade-out');
			}

			setTimeout(function(){
				permission_dialog.remove();

				if(cartbounty_pn.backdrop){
					backdrop.remove();
				}

			}, 500);
		}

		if(timePeriod != 0){ //If test mode enabled - do not set this value
			
			if(setLocalStorage){
				localStorage.setItem('cartbounty_pro_pn_last_time', currentTime);
			}
		}
	}

	//Function for encoding VAPID public key
	function urlBase64ToUint8Array(base64String) {
		const padding = '='.repeat((4 - base64String.length % 4) % 4);
		const base64 = (base64String + padding)
		.replace(/\-/g, '+')
		.replace(/_/g, '/');

		const rawData = window.atob(base64);
		const outputArray = new Uint8Array(rawData.length);

		for (var i = 0; i < rawData.length; ++i) {
			outputArray[i] = rawData.charCodeAt(i);
		}
		return outputArray;
	}

	startPushNotifications();

	jQuery('#cartbounty-pro-push-notification-permission-submit').on('click', requestNotificationPermission);
	jQuery('#cartbounty-pro-push-notification-permission-request-deny, #cartbounty-pro-push-notification-permission-close, #cartbounty-pro-push-notification-permission-backdrop').on('click', closePermissionDialog);

})(jQuery);