(function( $ ) {
	'use strict';
	 
	 jQuery(document).ready(function(){

		//Show or hide report options
		function toggleReportOptions(event){
			event.stopPropagation(); //Prevent the click event from bubbling to the document
			var tag_parent_element = jQuery(this).parent();
			var tag_parent_active_class = 'cartbounty-pro-report-options-active';

			if(!tag_parent_element.hasClass( tag_parent_active_class )){
				tag_parent_element.addClass( tag_parent_active_class );
				jQuery(document).on("click", closeReportOptions); //Attach event listener if the tooltip open

			}else{
				tag_parent_element.removeClass(tag_parent_active_class);
				jQuery(document).off("click", closeReportOptions); //Remove event listener if the tooltip closed
			}
		}

		//Close report options in case clicked outside of options window
		function closeReportOptions(event){
			var tooltip = jQuery(".cartbounty-pro-options-tooltip");
			if (!tooltip.is(event.target) && tooltip.has(event.target).length === 0) { // If clicked outside the option window - remove the class
				tooltip.parent().removeClass("cartbounty-pro-report-options-active");
				jQuery(document).off("click", closeReportOptions);
			}
		}

		//Show or hide calendar
		function toggleCalendar(event){
			event.stopPropagation(); //Prevent the click event from bubbling to the document
			var tag_parent_element = jQuery(this).parent();
			var tag_parent_active_class = 'cartbounty-pro-calendar-open';

			if(!tag_parent_element.hasClass( tag_parent_active_class )){
				jQuery('.cartbounty-pro-icon-button-container').removeClass('cartbounty-pro-report-options-active'); //Close report options
				tag_parent_element.addClass( tag_parent_active_class );

			}else{
				tag_parent_element.removeClass(tag_parent_active_class);
			}
		}

		//Close calendar
		function closeCalendar(){
			var tag_parent_element = jQuery("#cartbounty-pro-period-dropdown-container").parent();
			var tag_parent_active_class = 'cartbounty-pro-calendar-open';
			tag_parent_element.removeClass(tag_parent_active_class);
		}

		//Enable or disable a specific report options using Ajax
		function updateReportsOptions(){
			var item = jQuery(this);
			var action = item.data('action');
			var startDate = jQuery('#cartbounty-daypicker-start-date-input-duplicate');
			var endDate = jQuery('#cartbounty-daypicker-end-date-input-duplicate');
			var selectedPeriod = jQuery('.cartbounty-daypicker-periods input[type=checkbox]:checked');
			var comparePeriod = jQuery('.cartbounty-daypicker-comparison-options input[type=checkbox]:checked');
			var skeletonScreenClass = 'cartbounty-pro-loading-skeleton-screen';
			var reportsContainer = jQuery('#cartbounty-pro-abandoned-cart-quick-stats-container');
			var currencySelector = jQuery('#cartbounty-pro-abandoned-cart-stats-currency select');
			var mapName = jQuery('#cartbounty-pro-abandoned-carts-by-country-report-name');
			var mapNameContainer = jQuery('#cartbounty-pro-abandoned-carts-by-country-report-name-container');
			var currency = '';
			
			if(currencySelector !== 'undefined'){
				currency = currencySelector.val();
			}

			if( action == 'update_charts' ){
				reportsContainer = jQuery('#cartbounty-pro-charts-container');
			}else if( action == 'update_top_product_count' ){
				reportsContainer = jQuery('#cartbounty-pro-top-abandoned-products-container');
			}else if( action == 'update_map_report' || action == 'update_country_count'  ){
				reportsContainer = jQuery('#cartbounty-pro-abandoned-carts-by-country-container');
				mapNameContainer.addClass(skeletonScreenClass);
				addMapHeight();
			}
			
			var data = {
				nonce				: item.data('nonce'),
				action				: action,
				value				: item.prop('value'),
				currency 			: currency,
				status				: item.prop('checked'),
				name				: item.data('name'),
				start_date 			: startDate.val(),
				end_date 			: endDate.val(),
				period 				: selectedPeriod.val(),
				compare 			: comparePeriod.val()
			};

			reportsContainer.addClass(skeletonScreenClass);

			jQuery.post(cartbounty_pro_admin_data.ajaxurl, data,
			function(response){
				if ( response.success == true ){
					reportsContainer.html(response.data.report_data); //Updating quick stats

					if( action == 'update_charts' ){
						var chart_type = response.data.chart_type;
						var active_charts = response.data.active_charts;
						var currency_symbol = response.data.currency_symbol;
						initializeCharts(chart_type, active_charts, currency_symbol);

					} else if( action == 'update_map_report' || action == 'update_country_count' ){
						initializeMap(currency_symbol);
						mapName.text(response.data.map_report_name); //Updating map name
					}

				}else{
					console.log('An error occurred while updating quick stats.');
				}

				reportsContainer.removeClass(skeletonScreenClass);
				mapNameContainer.removeClass(skeletonScreenClass);
			});
		}

		function addLoadingIndicator(){ //Adding loading indicator once Submit button pressed
			jQuery(this).addClass('cartbounty-pro-loading');
		}

		//Function that is added as a callback once DayPicker has fully loaded
		function onDayPickerLoaded() {
			jQuery("#cartbounty-daypicker-apply").on("click", updateReports);
			jQuery("#cartbounty-daypicker-close").on("click", closeCalendar);
			jQuery(".cartbounty-pro-progress").on("click", addLoadingIndicator );

			//Display reports on first page load
			setTimeout(function(){
				updateReports.call(jQuery('#cartbounty-daypicker-apply'), null);
			}, 300);
			
		}

		function getTipOptions(){
			return {
				tipShadow			: "drop-shadow(2px 2px 10px rgba(0,0,0,0.07))",
				tipStrokeWidth		: 0.5,
				tipStrokeOpacity	: 0.1,
				tipTextPadding		: 20,
				tipFontSize			: 13,
				tipPointerSize		: 0,
				tipPreferredAnchor	: "left",
			};
		}

		//Handling date period changes and report updates
		function updateReports(e){
			//If function triggered via calendar submit form - prevent form from submitting
			if(e && e.type === 'click'){
				e.preventDefault();
			}
			var element = jQuery(this);
			var startDate = jQuery('#cartbounty-daypicker-start-date-input-duplicate');
			var endDate = jQuery('#cartbounty-daypicker-end-date-input-duplicate');
			var selectedPeriod = jQuery('.cartbounty-daypicker-periods input[type=checkbox]:checked');
			var comparePeriod = jQuery('.cartbounty-daypicker-comparison-options input[type=checkbox]:checked');
			var quickContainer = jQuery('#cartbounty-pro-abandoned-cart-quick-stats-container');
			var chartContainer = jQuery('#cartbounty-pro-charts-container');
			var periodDropdownContainer = jQuery('#cartbounty-pro-period-dropdown-container');
			var topProductContainer = jQuery('#cartbounty-pro-top-abandoned-products-container');
			var map = jQuery('#cartbounty-pro-abandoned-carts-by-country-container');
			var mapNameContainer = jQuery('#cartbounty-pro-abandoned-carts-by-country-report-name-container');
			var skeletonScreenClass = 'cartbounty-pro-loading-skeleton-screen';
			var currency = element.val();

			if(currency == ''){ //In case currency value is empty, try to get current currency selected from the currency select (necessary in case of calcendar date submit)
				var currencySelector = jQuery('#cartbounty-pro-abandoned-cart-stats-currency select');
				if(currencySelector !== 'undefined'){
					currency = currencySelector.val();
				}
			}

			addMapHeight();

			quickContainer.addClass(skeletonScreenClass);
			chartContainer.addClass(skeletonScreenClass);
			periodDropdownContainer.addClass(skeletonScreenClass);
			topProductContainer.addClass(skeletonScreenClass);
			map.addClass(skeletonScreenClass);
			mapNameContainer.addClass(skeletonScreenClass);

			var data = {
				nonce				: element.data('nonce'),
				action				: element.data('action'),
				currency 			: currency,
				start_date 			: startDate.val(),
				end_date 			: endDate.val(),
				period 				: selectedPeriod.val(),
				compare 			: comparePeriod.val(),
				current_url 		: window.location.href
			};

			jQuery.post(cartbounty_pro_admin_data.ajaxurl, data,
			function(response){

				if( response.success == true ){
					element.removeClass('cartbounty-pro-loading');
					history.pushState({}, '', response.data.url); //Changing URL according to submitted period
					periodDropdownContainer.html(response.data.period_dropdown); //Updating dropdown contents 
					quickContainer.html(response.data.report_data); //Updating quick stats
					chartContainer.html(response.data.chart_data); //Updating charts
					topProductContainer.html(response.data.top_products); //Update top products
					map.html(response.data.map_data); //Update map data
					var chart_type = response.data.chart_type;
					var active_charts = response.data.active_charts;
					var currency_symbol = response.data.currency_symbol;
					initializeCharts(chart_type, active_charts, currency_symbol);
					initializeMap(currency_symbol);

				}else{
					console.log('An error occurred while updating the report period');
				}

				quickContainer.removeClass(skeletonScreenClass);
				chartContainer.removeClass(skeletonScreenClass);
				periodDropdownContainer.removeClass(skeletonScreenClass);
				topProductContainer.removeClass(skeletonScreenClass);
				map.removeClass(skeletonScreenClass);
				mapNameContainer.removeClass(skeletonScreenClass);
			});
		}

		//If Daypicker exists - display calendar
		if(typeof CartBountyDayPicker !== 'undefined'){
			var daypicker = cartbounty_pro_admin_data.daypicker;
			var options = {
				'id'                    : daypicker.id,
				'action'                : daypicker.action,
				'nonce'                 : daypicker.nonce,
				'mode'                  : daypicker.mode,
				'showOutsideDays'       : daypicker.showOutsideDays,
				'defaultStartDate'      : new Date(daypicker.defaultStartDate),
				'defaultEndDate'        : new Date(daypicker.defaultEndDate),
				'defaultDatePeriod'     : daypicker.defaultDatePeriod,
				'defaultFallbackPeriod' : daypicker.defaultFallbackPeriod,

				'defaultComparison'     : daypicker.defaultComparison,
				'dateFormat'            : daypicker.dateFormat, //Nov 1, 2023
				'minFromDate'           : new Date(daypicker.minFromDate),
				'maxToDate'             : new Date(daypicker.maxToDate),
				'weekStartsOn'          : daypicker.weekStartsOn,
				'dir'                   : daypicker.dir,
				'language'              : daypicker.language,
				'componentNames'        : daypicker.componentNames,
				'comparisonOptions'     : daypicker.comparisonOptions,
				'datePeriods'           : daypicker.datePeriods,
				'onLoaded'           	: onDayPickerLoaded //Callback once the Daypicker has finished loading
			}
			CartBountyDayPicker( options );
		}

		//Function for switching between chart types
		function switchActiveChart(){
			var button = jQuery(this);
			var button_parent = button.parent();
			var chart_type = button.data('name');
			var chartContainer = jQuery('#cartbounty-pro-charts-container');
			var skeletonScreenClass = 'cartbounty-pro-loading-skeleton-screen';
			
			button_parent.find('.cartbounty-pro-chart-type-trigger').removeClass('cartbounty-pro-chart-type-active');
			button.addClass('cartbounty-pro-chart-type-active');
			chartContainer.addClass(skeletonScreenClass);
			
			var data = {
				nonce				: button.data('nonce'),
				action				: button.data('action'),
				value 				: chart_type
			};

			jQuery.post(cartbounty_pro_admin_data.ajaxurl, data,
			function(response){
				var active_charts = false;
				var currency_symbol = '';

				if ( response.success == true ){
					chart_type = response.data.chart_type;
					active_charts = response.data.active_charts;
					currency_symbol = response.data.currency_symbol;
				}
				initializeCharts( chart_type, active_charts, currency_symbol );
				chartContainer.removeClass(skeletonScreenClass);
			});
		}

		//Function for formatting tip value
		//If currency must be displayed - adding currency sign and making sure values with currency have two decimal places
		function formatTipValue(d, isCurrency, currencySymbol, isRate = false){
			var rateSymbol = '';

			if(!isCurrency){
				currencySymbol = '';
			}else{
				d = d.toFixed(2); //Adding two decimal places to the number
			}

			if(isRate){
				rateSymbol = '%';
			}

			return currencySymbol + d.toString() + rateSymbol;
		}

		//Function that displays charts on Dashboard
		function initializeCharts(chartType = false, activeCharts = false, currencySymbol = ''){
			if(typeof d3 !== 'undefined' && typeof Plot !== 'undefined'){
				
				if( !chartType ){ //If chart type not provided - use the one passed during page load
					var chartType = cartbounty_pro_admin_data.chart_type;
				}

				if( !activeCharts ){ //If active charts not provided - use the ones passed during page load
					var activeCharts = cartbounty_pro_admin_data.active_charts;
				}

				if( !currencySymbol ){ //If selected currency not provided - use the one passed during page load
					var currencySymbol = cartbounty_pro_admin_data.currency_symbol;
				}
				
				//Activate charts on page load
				if(Object.keys(activeCharts).length > 0 ){ //If we have active charts
					for(var key in activeCharts) {
						if (activeCharts.hasOwnProperty(key)) {
							var value = activeCharts[key];
							var chartId = 'chart-' + value;

							if(jQuery('#' + chartId).length > 0){ //If chart element has been found
								var chartStartDate = chartId.replace(/-/g, '_') + '_start_date'; //Retrieve start date
								var chartEndDate = chartId.replace(/-/g, '_') + '_end_date'; //Retrieve end date
								var chartCurrentPeriodData = chartId.replace(/-/g, '_') + '_current_period_data'; //Retrieve current period data
								var chartPreviousPeriodData = chartId.replace(/-/g, '_') + '_previous_period_data'; //Retrieve previous period data
								var chartIsCurrency = chartId.replace(/-/g, '_') + '_currency'; //Determine if the chart type needs to display currency or not
								
								var startDate = window[chartStartDate];
								var endDate = window[chartEndDate];
								var currentPeriodData = window[chartCurrentPeriodData];
								var previousPeriodData = window[chartPreviousPeriodData];
								var isCurrency = window[chartIsCurrency];
								drawChart(startDate, endDate, currentPeriodData, previousPeriodData, '#' + chartId, chartType, isCurrency, currencySymbol);
							}
						}
					}
				}

				//Function adds hours to a date
				function addHoursToDate(date, hours){
					var date = new Date(date);
					date.setHours(date.getHours() + hours);
					return date;
				}

				//Function subtracts hours from a date
				//Using this to position rectangle in the middle of the X-axis tip by subtracting half a day
				function subtractHoursFromDate(date, hours){
					var date = new Date(date);
					date.setHours(date.getHours() - hours);
					return date;
				}

				//Function formats a date according to a locale
				function formatDate(date, locale){
					var newDate = new Intl.DateTimeFormat(locale, {
					  year 	: 'numeric',
					  month : 'long',
					  day 	: 'numeric'
					}).format(date);
					return newDate;
				}

				//Function for formatting thousands by adding K values to them
				//If chart needs to display currency value, also adding it to the value
				function formatYTicks(d, isCurrency, currencySymbol){
					if(!isCurrency){
						currencySymbol = '';
					}
					return d => d >= 1000 ? currencySymbol + `${d / 1000}K` : currencySymbol + d.toString();
				}

				//Function to find the next even hundred or thousand
				function getNextEvenRoundNumber(value) {
					var roundedValue;
					if (value <= 100) {
						roundedValue = Math.ceil(value);
						//Find the next even number
						return roundedValue % 2 === 0 ? roundedValue : roundedValue + 1;
					} else {
						roundedValue = Math.ceil(value);
						//If in the hundreds or thousands, round up to the next even hundred or thousand
						var roundUpTo = roundedValue < 1000 ? 100 : 1000;
						return Math.ceil(roundedValue / roundUpTo / 2) * roundUpTo * 2;
					}
				}

				//Function retrieves min, max and interval values from a given data array of values
				function getChartValues(data){
					var values = data.map(d => d.Value);
					var max = Math.max(...values);
					max = getNextEvenRoundNumber(max);
					var interval = max / 2;
					var items = {
						'min'		: 0,
						'max'		: max,
						'interval'	: interval,
					}
					return items;
				}

				//Function for calculating how wide the chart should be depending on the amount days in the data
				function calculateChartWidth(data){
					var width = 0;
					var days = data.length;
					var pixelsPerYear = 620;
					var daysPerYear = 365;
					var minWidth = jQuery(".cartbounty-pro-report-content-chart").width();
					var chartWidth = (days / daysPerYear) * pixelsPerYear;
					length = Math.max(chartWidth, minWidth); //Select whichever is the highest number from both
					return Math.round(length);
				}

				//Create binned data to have a start and end for each bin
				//Necessary if creating rectY plot type chart
				function createBinnedData(dataArray){
					var binnedData = [];

					dataArray.forEach(function(dataPoint, index, array) {
						var endDate;
						//Determine the end date for the bin. If it's the last element,
						//Add 24 hours to create an end date; otherwise, use the next element's date
						if(index < array.length - 1) {
							endDate = array[index + 1].Date;
						}else{
							endDate = addHoursToDate(dataPoint.Date, 24);
						}

						var binData = {
							Value: 	dataPoint.Value,
							Date: 	dataPoint.Date,
							Start: 	subtractHoursFromDate(dataPoint.Date, 12),
							End: 	subtractHoursFromDate(endDate, 12)
						};

						binnedData.push(binData);
					});

					return binnedData;
				}

				//Function for creating charts
				function drawChart(startDate, endDate, currentPeriodData, previousPeriodData, containerId, chartType, isCurrency, currencySymbol){
					var container = jQuery(containerId);
					var values = getChartValues(currentPeriodData);

					//Converting count value to a number
					for (var i = 0; i < currentPeriodData.length; i++){
						if(chartType == 'line'){ //In case of using a line chart - convert date strings to date objects
							currentPeriodData[i].Date = new Date(currentPeriodData[i].Date);
						}
						currentPeriodData[i].Value = parseFloat(currentPeriodData[i].Value);
					}

					var options = {
						width 				: calculateChartWidth(currentPeriodData),
						height 				: 230,
						locale 				: cartbounty_pro_admin_data.locale,
						type 				: 'utc',
						color 				: '#ececec',
						bottomBorderColor 	: '#dddddd',
						currentPeriodColor 	: '#818181',
						clamp 				: true,
						dashes 				: '5,7',
						opacity 			: 0.1,
						labelArrow 			: 'none', //No arrow next to label
						tickSize 			: 0, //Do not draw ticks
						pointerRadius 		: 500,
					}

					const tip = getTipOptions();

					let emptyText = [];

					if( currentPeriodData.length === 0 ){
						emptyText = Plot.text([cartbounty_pro_admin_data.report_translations.missing_chart_data], {
							fontSize 	: 13,
							frameAnchor : "middle",
						})
					}

					if(chartType == "bar"){
						var binnedData = createBinnedData(currentPeriodData); //Binned data necessary only for plotting RectY
						var plot = Plot.plot({
							width 		: options.width,
							height 		: options.height,
							x: {
								type 	: options.xAxisType,
							},
							y: {
								domain 	: [values.min, values.max],
								clamp 	: options.clamp,
							},
							marks: [
								Plot.rectY(binnedData, Plot.pointerX({ //Adding vertical line on hover
									x1 			: "Start",
									x2 			: "End",
									y1 			: values.min,
									y2 			: values.max,
									fill 		: options.color,
									maxRadius 	: options.pointerRadius
								})),
								Plot.gridY({ //Adding vertical grid lines
									strokeDasharray : options.dashes,
									strokeOpacity 	: options.opacity,
									interval 		: values.interval
								}),
								Plot.ruleY([values.min], { //Adding bottom border line
									stroke 	: options.bottomBorderColor,
								}),
								Plot.axisX({ //formatting X axis
									fill 		: options.currentPeriodColor,
									color 		: options.bottomBorderColor,
								}),
								Plot.axisY({ //formatting Y axis
									label 		: '',
									labelArrow 	: options.labelArrow,
									tickSize 	: options.tickSize,
									tickFormat 	: formatYTicks(d => d, isCurrency, currencySymbol),
									interval 	: values.interval,
									fill 		: options.currentPeriodColor,
								}),
								Plot.rectY(binnedData, {
									x1 		: "Start", // X-coordinate for the left side of the rectangle
									x2 		: "End",   // X-coordinate for the right side of the rectangle
									y 		: "Value",  // Y-coordinate (height) of the rectangle
									fill 	: options.currentPeriodColor,
									insetLeft 	: 0.5, //Distance between bars
									insetRight 	: 0.5, //Distance between bars
									insetTop 	: -0.5, //Making bar a little bit higher due to dashed horizontal grid lines
								}),
								Plot.tip(binnedData, Plot.pointerX({ //Adding tooltip
									x1 				: "Start",
									x2 				: "End",
									y1 				: values.min,
									y2 				: values.max,
									title 			: (d) => [formatDate(d.End, options.locale), formatTipValue(d.Value, isCurrency, currencySymbol)].join("\t\t"),
									pathFilter 		: tip.tipShadow,
									strokeWidth 	: tip.tipStrokeWidth,
									strokeOpacity 	: tip.tipStrokeOpacity,
									textPadding 	: tip.tipTextPadding,
									fontSize		: tip.tipFontSize,
									pointerSize 	: tip.tipPointerSize,
									preferredAnchor : tip.tipPreferredAnchor,
									maxRadius 		: options.pointerRadius,
								})),
								emptyText,
							]					
						});

					}else if(chartType == "line"){
						var plot = Plot.plot({
							width 		: options.width,
							height 		: options.height,
							x: {
								type 	: options.xAxisType
							},
							y: {
								domain 	: [values.min, values.max],
								clamp 	: options.clamp,
							},
							marks: [
								Plot.ruleX(currentPeriodData, Plot.pointerX({ //Adding vertical line on hover
									x 			: "Date",
									py 			: "Value",
									stroke 		: options.color,
									maxRadius 	: options.pointerRadius
								})),
								Plot.gridY({ //Adding vertical grid lines
									strokeDasharray : options.dashes,
									strokeOpacity 	: options.opacity,
									interval 		: values.interval
								}),
								Plot.ruleY([values.min], { //Adding bottom border line
									stroke 	: options.bottomBorderColor,
								}),
								Plot.axisX({ //formatting X axis
									fill 	: options.currentPeriodColor,
									color 	: options.bottomBorderColor
								}),
								Plot.axisY({ //formatting Y axis
									label 		: '',
									labelArrow 	: options.labelArrow,
									tickSize 	: options.tickSize,
									tickFormat 	: formatYTicks(d => d, isCurrency, currencySymbol),
									interval 	: values.interval,
									fill 		: options.currentPeriodColor,
								}),
								Plot.line(currentPeriodData, {
									x 			: "Date",
									y 			: "Value",
									strokeWidth : 1,
									stroke 		: options.currentPeriodColor,
									curve 		: "monotone-x",
								}),
								Plot.dot(currentPeriodData, Plot.pointerX({
									x 			: "Date",
									y 			: "Value",
									symbol 		: 'circle',
									fill 		: "#976dfb",
									maxRadius 	: options.pointerRadius,
								})),
								Plot.tip( currentPeriodData, Plot.pointerX({ //Adding tooltip
									x 				: "Date",
									y1 				: values.min,
									y2 				: values.max,
									title 			: (d) => [formatDate(d.Date, options.locale), formatTipValue(d.Value, isCurrency, currencySymbol)].join("\t\t"),
									pathFilter 		: tip.tipShadow,
									strokeWidth 	: tip.tipStrokeWidth,
									strokeOpacity 	: tip.tipStrokeOpacity,
									textPadding 	: tip.tipTextPadding,
									fontSize		: tip.tipFontSize,
									pointerSize 	: tip.tipPointerSize,
									preferredAnchor : tip.tipPreferredAnchor,
									maxRadius 		: options.pointerRadius,
								})),
								emptyText,
							]					
						});
					}

					container.html(plot);
				}
			}
		}

		//Function that displays country data on Dashboard
		function initializeMap(currencySymbol = ''){
			if(typeof d3 !== 'undefined' && typeof Plot !== 'undefined'){

				if( !currencySymbol ){ //If selected currency not provided - use the one passed during page load
					var currencySymbol = cartbounty_pro_admin_data.currency_symbol;
				}
				
				var isCurrency = window['abandoned_cart_country_data_currency'];
				var isRate = window['abandoned_cart_country_data_rate'];
				var container = jQuery('#cartbounty-pro-country-map');

				//Function for calculating how wide the map should be
				function calculateMapWidth(){
					var mapWidth = container.width();
					return mapWidth || 640; //If map width is undefined, setting map width to 640
				}

				const mapWidth = calculateMapWidth();
				const mapData = cartbounty_pro_admin_data.countries;

				fetch(mapData).then((response) => response.json()).then((countries) => {
					//Exclude Antarctica from the dataset
					const filteredFeatures = countries.features.filter((feature) => feature.properties.name !== "Antarctica");
					const filteredCountries = {
						...countries,
						features: filteredFeatures,
					};

					createMap(filteredCountries);

					//At the end of the map initialization, trigger a custom event informing that map has been loaded
					jQuery('#cartbounty-pro-abandoned-carts-by-country-container').trigger('cartBountyMapLoaded');

				}).catch((error) => console.error("Error loading GeoJSON data:", error));

				function createMap(countries){
					var abandonedCartData = [];

					if(container.length > 0){ //If map element has been found
						if (Array.isArray(window.abandoned_cart_country_data)) {
							abandonedCartData = window.abandoned_cart_country_data;
						} else {
							abandonedCartData = [];
						}
					}

					//Calculate map height based on desired aspect ratio
					const aspectRatio = 16 / 10.5;
					const mapHeight = mapWidth / aspectRatio;
					const scaleFactor = 0.16;
					const scale = mapWidth * scaleFactor;
					const dataMap = new Map(abandonedCartData.map((d) => [d.country, +d.value]));

				 	//Defining map colors based on cart count
					const colorScale = d3.scaleQuantize()
					.domain([0, d3.max(abandonedCartData, (d) => d.value)])
					.range(["#bdbcbc", "#a09f9f", "#828282", "#676767", "#414141"]);

					const options = {
						tipPointerSize 	: 10,
						pointerRadius 	: 50,
					};

					const tip = getTipOptions();

					// Calculate centroids and prepare tooltip data
					const centroids = countries.features.map((feature) => {
						const countryName = feature.properties.name;
						const countryCode = feature.id;
						const countryValue = dataMap.get(countryCode) || 0;
						const centroid = d3.geoCentroid(feature);

						return {
							name 		: countryName,
							value 		: countryValue,
							coordinates : centroid,
						};
					});

					const map = Plot.plot({
						projection: ({ width, height }) => d3.geoMercator()
							.scale(scale) //Set scale
							.translate([width / 2, height / 1.42]), //Center the map
						marks: [
							Plot.geo(countries, {
								fill: (d) => {
									const count = dataMap.get(d.id) || 0;
									return count === 0 ? "#dcdcdc" : colorScale(count);
								},
								stroke: "#ffffff", // White stroke for boundaries
								title: (d) => d.properties ? [`${d.properties.name}:`, formatTipValue(dataMap.get(d.id) || 0, isCurrency, currencySymbol, isRate)].join("\t\t") : cartbounty_pro_admin_data.report_translations.missing_chart_data,
							}),
							Plot.tip(centroids, Plot.pointer({
								x 				: (d) => d.coordinates[0], 
								y 				: (d) => d.coordinates[1],
								title 			: (d) => d.value ? [`${d.name}:`, formatTipValue(d.value, isCurrency, currencySymbol, isRate)].join("\t\t") : null,
								fontSize 		: tip.tipFontSize,
								textAnchor 		: "middle",
								dy 				: "0",
								pathFilter 		: tip.tipShadow,
								strokeWidth 	: tip.tipStrokeWidth,
								strokeOpacity 	: tip.tipStrokeOpacity,
								textPadding 	: tip.tipTextPadding,
								pointerSize 	: options.tipPointerSize,
								preferredAnchor : tip.tipPreferredAnchor,
								maxRadius 		: options.pointerRadius,
							})),
						],
						width 	: mapWidth,
						height 	: mapHeight,
						margin 	: 0,
					});

					container.html(map);
				}
			}
		}

		//Adding temporary map height while switching report type or updating map
		function addMapHeight(){
			var map = jQuery('#cartbounty-pro-abandoned-carts-by-country-container');
			var currentHeight = map.height();
			map.css('height', currentHeight + 'px');
		}

		//Removing temporary map height
		function removeMapHeight(){
			var map = jQuery('#cartbounty-pro-abandoned-carts-by-country-container');
			map.css('height', '');
		}

		initializeCharts(); //Display charts on Dashboard page load
		initializeMap(); //Display map on Dashboard page load		

		jQuery(document).on('change', '#cartbounty-pro-abandoned-cart-stats-options input, #cartbounty-pro-top-product-count select, #cartbounty-pro-available-map-reports select, #cartbounty-pro-country-count select', updateReportsOptions);
		jQuery(document).on('change', '#cartbounty-pro-abandoned-cart-stats-currency select', updateReports);
		jQuery(".cartbounty-pro-report-options-trigger").on("click", toggleReportOptions );
		jQuery("#cartbounty-pro-period-dropdown-container").on("click", toggleCalendar );
		jQuery(".cartbounty-pro-chart-type-trigger").on("click", switchActiveChart );
		jQuery("#cartbounty-pro-abandoned-carts-by-country-container").on("cartBountyMapLoaded", removeMapHeight );
	});

})( jQuery );