/*
 *  Project: jQuery Modula 2
 *  Version: 1.0
 *  Description: Artistic gallery
 *  Author: WP Modula
 */

if (
	typeof jQuery !== 'undefined' &&
	window.ModulaIsotope &&
	typeof jQuery.fn.modulaisotope === 'undefined'
) {
	jQueryBridget('modulaisotope', window.ModulaIsotope, jQuery);
}

window.modulacheckDevice = function ( opts ) {
	if ( 'undefined' != typeof opts ) {
		var devices = true;
		if ( 'undefined' != typeof opts.lightbox_devices && 'both' !== opts.lightbox_devices ) {
			if ( 'mobile' == opts.lightbox_devices ) {
				devices = 1024 > jQuery( window ).width();
			} else {
				devices = 1024 < jQuery( window ).width();
			}
		}
		return devices;
	}
	return false;
};

// Compatibility with WPBakery Page Builder( reset modula after section go full width )
jQuery(document).on(
	'vc-full-width-row-single vc-full-width-row',
	function (event, element) {
		if (jQuery('body').find('.modula').length > 0) {
			jQuery(window).trigger('modula-update');
		}
	}
);

// Compatibility with Elementor( reset modula after section go full width )
jQuery(window).on('elementor/frontend/init', function () {
	if (window.elementorFrontend) {
		window.elementorFrontend.hooks.addAction(
			'frontend/element_ready/global',
			function ($scope) {
				if (jQuery('body').find('.modula').length > 0) {
					//jQuery(window).trigger('modula-update');
				}
			}
		);
	}
});

(function ($, window, document, undefined) {
	// Create the defaults once
	var pluginName = 'modulaGallery',
		defaults = {
			resizer: '/',
			keepArea: true,
			type: 'creative-gallery',
			columns: 12,
			height: 800,
			desktopHeight: 800,
			mobileHeight: 800,
			tabletHeight: 800,
			gutter: 10,
			desktopGutter: 10,
			mobileGutter: 10,
			tabletGutter: 10,
			enableTwitter: false,
			enableFacebook: false,
			enableWhatsapp: false,
			enablePinterest: false,
			enableLinkedin: false,
			enableEmail: false,
			lazyLoad: 0,
			initLightbox: false,
			lightbox: 'fancybox',
			lightboxOpts: {
				Toolbar: {
					parentEl: function (toolbar) {
						return toolbar.instance.container.querySelector(
							'.fancybox__col'
						);
					},
				},
			},
			inView: false,
			originLeft: true,
		};

	// The actual plugin constructor
	function Plugin(element, options) {
		this.element = element;
		this.$element = $(element);
		this.$itemsCnt = this.$element.find('.modula-items');
		this.$items = this.$itemsCnt.find('.modula-item');

		this.options = $.extend({}, defaults, options);

		this._defaults = defaults;
		this._name = pluginName;

		this.tiles = [];
		this.$tilesCnt = null;
		this.completed = false;
		this.lastWidth = 0;
		this.resizeTO = 0;
		this.isIsotope = false;
		this.isLazyLoaded = true;

		// Initiate Gallery
		this.init();
	}

	// initialization of our modula instance
	Plugin.prototype.init = function () {
		var instance = this,
			viewport = document.documentElement.clientWidth;
		if (viewport < 768) {
			this.options.gutter = this.options.mobileGutter;
		} else if (viewport >= 768 && viewport <= 992) {
			this.options.gutter = this.options.tabletGutter;
		} else {
			this.options.gutter = this.options.desktopGutter;
		}
		// Trigger event before init
		$(document).trigger('modula_api_before_init', [instance]);

		if ('custom-grid' === this.options.type) {
			this.createCustomGallery();
		} else if ('creative-gallery' == this.options.type) {
			this.createGrid();
		} else if ('grid' == this.options.type) {
			if ('automatic' == this.options.grid_type) {
				this.createAutoGrid();
			} else {
				this.createColumnsGrid();
			}
		}

		// Fix for custom grid elements not organizing correctly on some themes
		// where at first the scrollbar is missing
		if (
			'custom-grid' === this.options.type &&
			$(window).height() < $('html').height()
		) {
			instance.onResize(instance);
		}

		let resizeTimeout;
		let resizeObserverTimeout;

		$(window).resize(function () {
			clearTimeout(resizeTimeout);
			resizeTimeout = setTimeout(function () {
				instance.onResize(instance);
			}, 150);
		});

		const resizeObserver = new ResizeObserver((entries) => {
			clearTimeout(resizeObserverTimeout);
			resizeObserverTimeout = setTimeout(() => {
				instance.onResize(instance);
			}, 150);
		});

		resizeObserver.observe(instance.$element[0]);

		$(window).on('modula-update', function () {
			instance.onResize(instance);
		});

		$(document).on('lazyloaded lazyload', function (evt) {
			var element = $(evt.target),
				parent,
				index,
				picElement;

			if (
				'modula' == element.data('source') ||
				'a3-lazyload' == element.data('source')
			) {
				element.data('size', {
					width: element.width(),
					height: element.height(),
				});
				parent = element.parents('.modula-item');
				parent.addClass('tg-loaded');

				// Support for picture element - add class to both img and picture parent
				picElement = element.closest('.pic');
				if (
					picElement.length &&
					picElement.prop('tagName') === 'PICTURE'
				) {
					picElement.addClass('tg-loaded');
				}

				index = instance.$items.not('.jtg-hidden').index(parent);
				instance.placeImage(index);

				if (instance.isIsotope) {
					if (
						'undefined' !==
						typeof instance.$itemsCnt.data('modulaisotope')
					) {
						instance.$itemsCnt.modulaisotope('layout');
					}
				}

				if (
					'grid' == instance.options.type &&
					'undefined' === typeof window.elementorFrontend &&
					'automatic' == instance.options.grid_type
				) {
					instance.$itemsCnt.justifiedGallery();
				}
			}
		});

		if (instance.options.inView) {
			jQuery(window).on(
				'DOMContentLoaded load resize scroll',
				function () {
					if (modulaInViewport(instance.$element)) {
						instance.$element.addClass('modula-loaded-scale');
					}
				}
			);
		}

		// Gives error on front
		/* new ResizeSensor( instance.$element, function() {
		 instance.onResize(instance);
		 });*/

		// Create social links
		this.setupSocial();

		// Add init class
		jQuery(instance.$element).addClass('modula-gallery-initialized');
		// Trigger custom gallery JS
		if (this.options.onComplete) {
			this.options.onComplete();
		}

		// Init lightox
		if (
			'fancybox' == instance.options['lightbox'] &&
			!instance.options['initLightbox']
		) {
			this.initLightbox();
		}

		// Trigger event after init
		$(document).trigger('modula_api_after_init', [instance]);

		setTimeout(() => {
			document.dispatchEvent(
				new Event('modula_gallery_initialized', {
					detail: { instance: instance },
				})
			);
		}, 100);
	};

	// function wich collect all the images for lightbox and initialize the lightbox.
	Plugin.prototype.initLightbox = function () {
		var self = this;

		self.$element.on('click', '.modula-no-follow', function (evt) {
			evt.preventDefault();
		});

		self.$element.on(
			'click keypress',
			'.modula-item-link:not( .modula-simple-link )',
			function (evt) {
				// Added accesibility support.
				if (evt.which !== 13 && evt.type !== 'click') {
					return;
				}
				evt.preventDefault();
				var clickedLink = jQuery(this);
				var links = $.map(self.$items, function (o) {
						if (
							jQuery(o).find(
								'.modula-item-link:not( .modula-no-follow )'
							).length > 0
						) {
							var link = jQuery(o).find(
									'.modula-item-link:not( .modula-simple-link )'
								),
								image = jQuery(o).find('.pic');
							return {
								src: image.data('full'),
								opts: {
									$thumb: image.parents('.modula-item'),
									caption: link.data('caption'),
									alt: image.attr('alt'),
									image_id: link.attr('data-image-id'),
									title: image.attr('title'),
								},
								current: jQuery(o).is(
									clickedLink.parents('.modula-item')
								),
							};
						}
					}),
					index = $.map(links, function (element, myIndex) {
						if (element.current) {
							return myIndex;
						}
					})[0];

				if ( modulacheckDevice( self.options ) ) {
					jQuery.modulaFancybox.open(
						links,
						self.options.lightboxOpts,
						index
					);
				}
			}
		);

		if ( self.options.copyCaptionMobile ) {
			var tapped = false, tappedTimeout;
			var galleryId = self.element.id;
			var doCopyCaption = function ( caption ) {
				var textEl = caption.querySelector( '.modula-caption-description' );
				var textToCopy = textEl ? textEl.textContent : caption.textContent;
				if ( ! textToCopy.trim() ) return;
				if ( navigator.clipboard && navigator.clipboard.writeText ) {
					navigator.clipboard.writeText( textToCopy.trim() ).catch( function ( err ) {
						console.error( 'Could not copy text: ', err );
					} );
				} else {
					var ta = document.createElement( 'textarea' );
					ta.value = textToCopy.trim();
					document.body.appendChild( ta );
					ta.select();
					document.execCommand( 'copy' );
					document.body.removeChild( ta );
				}
			};
			document.addEventListener( 'touchend', function ( e ) {
				var caption = e.target.closest( '.fancybox__caption' );
				if ( ! caption ) return;
				if ( ! caption.closest( '.modula-lightbox-' + galleryId ) ) return;
				e.preventDefault();
				e.stopPropagation();
				if ( ! tapped ) {
					tapped = true;
					tappedTimeout = setTimeout( function () { tapped = false; }, 400 );
				} else {
					clearTimeout( tappedTimeout );
					tapped = false;
					doCopyCaption( caption );
				}
			}, true );
		}
	};

	Plugin.prototype.trunc = function (v) {
		if (Math.trunc) {
			return Math.trunc(v);
		} else {
			v = +v;
			if (!isFinite(v)) return v;

			return v - (v % 1) || (v < 0 ? -0 : v === 0 ? v : 0);
		}
	};

	// Create custom grid gallery based on packery.
	Plugin.prototype.createCustomGallery = function () {
		var instance = this,
			size,
			containerWidth = this.$element.find('.modula-items').width(),
			plugin = this,
			columns = this.options.columns,
			viewport = document.documentElement.clientWidth;

		if ('1' == this.options.enableResponsive) {
			if (viewport <= 568) {
				columns = this.options.mobileColumns;
			} else if (viewport <= 768) {
				columns = this.options.tabletColumns;
			}
		}

		if (this.options.gutter > 0) {
			size =
				(containerWidth - this.options.gutter * (columns - 1)) /
				columns;
		} else {
			size = Math.floor((containerWidth / columns) * 1000) / 1000;
		}

		this.$items.not('.jtg-hidden').each(function (i, item) {
			var slot = {},
				widthColumns,
				heightColumns,
				auxWidth,
				auxHeight;

			widthColumns = $(item).data('width');
			heightColumns = $(item).data('height');

			if (widthColumns > 12) {
				widthColumns = 12;
			}

			if ('1' == plugin.options.enableResponsive) {
				auxWidth = widthColumns;
				auxHeight = heightColumns;

				if (1 == columns) {
					widthColumns = 1;
					heightColumns = (widthColumns * auxHeight) / auxWidth;
				} else {
					widthColumns = Math.round((columns * auxWidth) / 12);
					if (widthColumns < 1) {
						widthColumns = 1;
					}

					heightColumns = Math.round(
						(widthColumns * auxHeight) / auxWidth
					);
					if (heightColumns < 1) {
						heightColumns = 1;
					}
				}
			}

			slot.width =
				size * widthColumns +
				plugin.options.gutter * (widthColumns - 1);
			slot.height =
				Math.round(size) * heightColumns +
				plugin.options.gutter * (heightColumns - 1);

			$(item)
				.data('size', slot)
				.addClass('tiled')
				.addClass(slot.width > slot.height ? 'tile-h' : 'tile-v')
				.data('position');

			$(item).css($(item).data('size'));
			$(item)
				.find('.figc')
				.css({
					width: $(item).data('size').width,
					height: $(item).data('size').height,
				});

			// Load Images
			instance.loadImage(i);
		});

		var packery_args = {
			itemSelector: '.modula-item',
			layoutMode: 'packery',
			originLeft: plugin.options.originLeft,
			packery: {
				gutter: parseInt(plugin.options.gutter),
			},
		};

		this.$itemsCnt.modulaisotope(packery_args);
		this.isIsotope = true;
	};

	// Create Modula default gallery grid
	Plugin.prototype.createGrid = function () {
		var instance = this;

		// if ( this.options.width ) {
		// 	this.$itemsCnt.width(this.options.width);
		// }

		// if ( this.options.height ) {
		// 	this.$itemsCnt.height(this.options.height);
		// }
		var viewport = document.documentElement.clientWidth;

		if (viewport <= 568) {
			instance.options.height = instance.options.mobileHeight;
		} else if (viewport <= 768) {
			instance.options.height = instance.options.tabletHeight;
		} else {
			instance.options.height = instance.options.desktopHeight;
		}

		this.$itemsCnt.data(
			'area',
			this.$itemsCnt.width() * this.options.height
		);

		this.lastWidth = this.$itemsCnt.width();

		for (var i = 0; i < this.$items.not('.jtg-hidden').length; i++) {
			this.tiles.push(instance.getSlot());
		}

		this.tiles.sort(function (x, y) {
			return x.position - y.position;
		});

		this.$items.not('.jtg-hidden').each(function (i, item) {
			var slot = instance.tiles[i];

			$(item).data('size', slot);

			$(item)
				.addClass('tiled')
				.addClass(slot.width > slot.height ? 'tile-h' : 'tile-v')
				.data('position');

			$(item).css({
				width: slot.width,
				height: slot.height,
			});

			$(item).find('.figc').css({
				width: slot.width,
				height: slot.height,
			});

			instance.loadImage(i);
		});

		if (!this.isIsotope) {
			var packery_args = {
				resizesContainer: false,
				itemSelector: '.modula-item',
				layoutMode: 'packery',
				originLeft: instance.options.originLeft,
				packery: {
					gutter: parseInt(instance.options.gutter),
				},
			};

			this.$itemsCnt.modulaisotope(packery_args);
			this.isIsotope = true;
		}
	};

	// initialize the justified gallery.
	Plugin.prototype.createAutoGrid = function () {
		var plugin = this;

		this.$itemsCnt.justifiedGallery({
			rowHeight: this.options.rowHeight,
			margins: this.options.gutter,
			lastRow: this.options.lastRow,
			captions: false,
			border: 0,
			imgSelector: 'img.pic, picture.pic img',
			cssAnimation: true,
			imagesAnimationDuration: 700,
		});
	};

	// create the mansonry gallery
	Plugin.prototype.createColumnsGrid = function () {
		var instance = this;

		this.$itemsCnt.modulaisotope({
			// set itemSelector so .grid-sizer is not used in layout
			itemSelector: '.modula-item',
			// percentPosition: true,
			layoutMode: 'packery',
			originLeft: this.options.originLeft,
			packery: {
				// use element for option
				gutter: parseInt(this.options.gutter),
			},
		});

		// Load Images
		this.$items.each(function (index, el) {
			instance.loadImage(index);
		});

		this.isIsotope = true;
	};

	// generate a slot with random width and height for creative gallery
	// To Do: keep the ratio of picture when generate slot.
	Plugin.prototype.getSlot = function () {
		if (this.tiles.length == 0) {
			var tile = {
				top: 0,
				left: 0,
				width: this.$itemsCnt.width(),
				height: this.options.height,
				area: this.$itemsCnt.width() * this.options.height,
				position: 0,
			};

			return tile;
		}

		var maxTileIdx = 0;
		for (var i = 0; i < this.tiles.length; i++) {
			var tile = this.tiles[i];
			if (tile.area > this.tiles[maxTileIdx].area) {
				maxTileIdx = i;
			}
		}

		var tile = {};

		var maxTileData = this.tiles[maxTileIdx];

		if (maxTileData.width > maxTileData.height) {
			var randomMaxDelta =
				(maxTileData.width / 2) * this.options.randomFactor;

			maxTileData.prevWidth = maxTileData.width;
			maxTileData.width = Math.floor(
				maxTileData.width / 2 + randomMaxDelta * (Math.random() - 0.5)
			);

			tile = {
				top: maxTileData.top,
				left:
					maxTileData.left + maxTileData.width + this.options.gutter,
				width:
					maxTileData.prevWidth -
					maxTileData.width -
					this.options.gutter,
				height: maxTileData.height,
			};
		} else {
			var randomMaxDelta =
				(maxTileData.height / 2) * this.options.randomFactor;

			maxTileData.prevHeight = maxTileData.height;
			maxTileData.height = Math.floor(
				maxTileData.height / 2 + randomMaxDelta * (Math.random() - 0.5)
			);

			tile = {
				left: maxTileData.left,
				top: maxTileData.top + maxTileData.height + this.options.gutter,
				width: maxTileData.width,
				height:
					maxTileData.prevHeight -
					maxTileData.height -
					this.options.gutter,
			};
		}

		tile.area = tile.width * tile.height;
		tile.position = tile.top * 1000 + tile.left;

		maxTileData.position = maxTileData.top * 1000 + maxTileData.left;

		this.tiles[maxTileIdx] = maxTileData;
		this.tiles[maxTileIdx].area = maxTileData.width * maxTileData.height;

		return tile;
	};

	// Re-initialize the gallery
	Plugin.prototype.reset = function () {
		var instance = this;
		instance.tiles = [];

		if ('custom-grid' === this.options.type) {
			this.createCustomGallery();
		} else if ('creative-gallery' == this.options.type) {
			this.createGrid();
		} else if ('grid' == this.options.type) {
			if ('automatic' == this.options.grid_type) {
				this.createAutoGrid();
			} else {
				this.createColumnsGrid();
			}
		}

		instance.lastWidth = instance.$itemsCnt.width();

		// Trigger event after init
		$(document).trigger('modula_api_reset', [instance]);
	};

	// function used to reset the gallery
	Plugin.prototype.onResize = function (instance) {
		if (instance.lastWidth == instance.$itemsCnt.width()) return;

		var viewport = document.documentElement.clientWidth;

		if (viewport < 768) {
			this.options.gutter = this.options.mobileGutter;
		} else if (viewport >= 768 && viewport <= 992) {
			instance.options.gutter = instance.options.tabletGutter;
		} else {
			instance.options.gutter = this.options.desktopGutter;
		}

		clearTimeout(instance.resizeTO);
		instance.resizeTO = setTimeout(function () {
			if (instance.options.keepArea) {
				var area = instance.$itemsCnt.data('area');
				instance.$itemsCnt.height(area / instance.$itemsCnt.width());
			}

			instance.reset();

			if (instance.isIsotope) {
				instance.$itemsCnt
					.modulaisotope({
						packery: {
							originLeft: instance.options.originLeft,
							gutter: parseInt(instance.options.gutter),
						},
					})
					.modulaisotope('layout');
			}
		}, 100);
	};

	// load the image in order to get the width and heoght of the picture.
	Plugin.prototype.loadImage = function (index) {
		var instance = this,
			picElement = instance.$items
				.not('.jtg-hidden')
				.eq(index)
				.find('.pic'),
			source = picElement.is('img') ? picElement : picElement.find('img'),
			size = {};

		if ('0' != instance.options.lazyLoad) {
			instance.placeImage(index);
			return;
		}

		var img = new Image();
		img.onload = function () {
			size = { width: this.width, height: this.height };
			source.data('size', size);
			instance.placeImage(index);
		};

		if ('undefined' != source.attr('src')) {
			img.src = source.attr('src');
		} else {
			img.src = source.data('src');
		}
	};

	// function used to place the image in container based on the alignment select by the user.
	Plugin.prototype.placeImage = function (index) {
		if ('grid' == this.options.type) {
			return;
		}

		var $tile = this.$items.not('.jtg-hidden').eq(index);
		var $picElement = $tile.find('.pic');
		var $image = $picElement.is('img')
			? $picElement
			: $picElement.find('img');

		var tSize = $tile.data('size');
		var iSize = $image.data('size');

		if (typeof tSize == 'undefined') {
			return;
		}

		if (typeof iSize == 'undefined') {
			return;
		}

		var tRatio = tSize.width / tSize.height;
		var iRatio = iSize.width / iSize.height;

		var valign = $image.data('valign') ? $image.data('valign') : 'middle';
		var halign = $image.data('halign') ? $image.data('halign') : 'center';

		var cssProps = {
			top: 'auto',
			bottom: 'auto',
			left: 'auto',
			right: 'auto',
			width: 'auto',
			height: 'auto',
			margin: '0',
			maxWidth: '999em',
		};

		var newHeight = (tSize.width * iSize.height) / iSize.width;

		if (newHeight > tSize.height) {
			cssProps.width = tSize.width;
			cssProps.left = 0;

			switch (valign) {
				case 'top':
					cssProps.top = 0;
					break;
				case 'middle':
					cssProps.top =
						0 - (tSize.width * (1 / iRatio) - tSize.height) / 2;
					break;
				case 'bottom':
					cssProps.bottom = 0;
					break;
			}
		} else {
			cssProps.height = tSize.height;
			cssProps.top = 0;

			switch (halign) {
				case 'left':
					cssProps.left = 0;
					break;
				case 'center':
					cssProps.left =
						0 - (tSize.height * iRatio - tSize.width) / 2;
					break;
				case 'right':
					cssProps.right = 0;
					break;
			}
		}
		// Fix for the under-image effect
		if ($tile.hasClass('effect-under')) {
			cssProps.top =
				cssProps.top - $tile.find('.modula-item-content').height();
		}

		$image.css(cssProps);
		this.$items.not('.jtg-hidden').eq(index).addClass('tg-loaded');

		// Support for picture element - add class to picture parent if it exists
		if ($image.parent().prop('tagName') === 'PICTURE') {
			$image.parent().addClass('tg-loaded');
		}
	};

	// based on settings set the needed socials.
	Plugin.prototype.setupSocial = function () {
		if (
			this.options.enableTwitter ||
			this.options.enableFacebook ||
			this.options.enablePinterest ||
			this.options.enableLinkedin ||
			this.options.enableWhatsapp ||
			this.options.enableEmail
		) {
			setupSocials(this.$items);
		}
		if (this.options.enableTwitter) {
			setupTwitter(this.$items, this);
		}
		if (this.options.enableFacebook) {
			setupFacebook(this.$items, this);
		}
		if (this.options.enablePinterest) {
			setupPinterest(this.$items, this);
		}
		if (this.options.enableLinkedin) {
			setupLinkedIN(this.$items, this);
		}
		if (this.options.enableWhatsapp) {
			setupWhatsapp(this.$items, this);
		}
		if (this.options.enableEmail) {
			setupEmail(this.$items, this);
		}
	};

	// destroy the packery object.
	Plugin.prototype.destroy = function () {
		if (this.isPackeryActive) {
			this.$itemsCnt.packery('destroy');
			this.isPackeryActive = false;
		}
	};

	//credits James Padolsey http://james.padolsey.com/
	var qualifyURL = function (url) {
		var img = document.createElement('img');
		img.src = url; // set string url
		url = img.src; // get qualified url
		img.src = null; // no server request
		return url;
	};

	// get all the information that twitter needs
	var setupTwitter = function ($tiles, plugin) {
		$tiles.find('.modula-icon-twitter').click(function (e) {
			e.preventDefault();

			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			var $caption = image.data('caption');
			var $title = image.attr('title');
			var text = document.title;
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			if ($title.length > 0 && $caption.length > 0) {
				text = $.trim($title) + ' - ' + $.trim($caption);
			} else if ($title.length > 0) {
				text = $.trim($title);
			} else if ($caption.length > 0) {
				text = $.trim($caption);
			}

			var w = window.open(
				'https://twitter.com/intent/tweet?url=' +
					encodeURIComponent(newUrl) +
					'&text=' +
					encodeURI(text),
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);
			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	// get all the information that facebook needs
	var setupFacebook = function ($tiles, plugin) {
		$tiles.find('.modula-icon-facebook').click(function (e) {
			e.preventDefault();

			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			var url =
				'//www.facebook.com/sharer.php?u=' + encodeURIComponent(newUrl);

			var w = window.open(
				url,
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);
			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	// get all the information that whatsapp needs
	var setupWhatsapp = function ($tiles, plugin) {
		$tiles.find('.modula-icon-whatsapp').click(function (e) {
			e.preventDefault();
			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			var w = window.open(
				'https://api.whatsapp.com/send?text=' +
					encodeURIComponent(newUrl) +
					'&preview_url=true',
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);
			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	// get all the information that pinterest needs
	var setupPinterest = function ($tiles, plugin) {
		$tiles.find('.modula-icon-pinterest').click(function (e) {
			e.preventDefault();

			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			var $caption = image.data('caption');
			var $title = image.attr('title');
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			var text = document.title;

			if ($title.length > 0) {
				text = $.trim($title);
			} else if ($caption.length > 0) {
				text = $.trim($caption);
			}

			var url =
				'http://pinterest.com/pin/create/button/?url=' +
				encodeURIComponent(newUrl) +
				'&description=' +
				encodeURI(text);

			if ('undefined' !== typeof imageUrl && imageUrl.length > 0) {
				url += '&media=' + qualifyURL(imageUrl);
			}

			var w = window.open(
				url,
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);
			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	// get all the information that linkedin needs
	var setupLinkedIN = function ($tiles, plugin) {
		$tiles.find('.modula-icon-linkedin').click(function (e) {
			e.preventDefault();

			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			var url =
				'//linkedin.com/shareArticle?mini=true&url=' +
				encodeURIComponent(newUrl);

			var w = window.open(
				url,
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);
			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	// get all the information that email needs
	var setupEmail = function ($tiles, plugin) {
		$tiles.find('.modula-icon-email').click(function (e) {
			var subject = plugin.options.email_subject;

			let socialLink = $(this),
				image = $(this).parents('.modula-item').find('img.pic'),
				imageUrl = socialLink.data('modula-image-src'),
				currentPageUrl = window.location.href,
				imageID = socialLink.data('modula-item-id'),
				galleryID = socialLink.data('modula-gallery-id');
			// Create a URL object from the original URL
			const urlObj = new URL(currentPageUrl);
			const urlParams = new URLSearchParams(urlObj.search);

			// Update the parameters
			if ('undefined' !== typeof galleryID) {
				urlParams.set(
					'modula_gallery_id',
					encodeURIComponent(galleryID)
				);
			}
			if ('undefined' !== typeof imageID) {
				urlParams.set('modula_image_id', encodeURIComponent(imageID));
			}

			// Check if modulaMetaVars is defined
			if ('object' === typeof modulaMetaVars) {
				// Check if it's not empty
				if (0 !== Object.keys(modulaMetaVars).length) {
					// Cycle through the values of the object and get the .data() value of the socialLink
					for (const [key, value] of Object.entries(modulaMetaVars)) {
						let data = socialLink.data(value);
						// Update the parameters
						if ('undefined' !== typeof data) {
							urlParams.set(value, data);
						}
					}
				}
			}
			// Trigger event to allow for custom URL parameters
			document.dispatchEvent(
				new CustomEvent('modula_social_url_params', {
					detail: {
						url: urlObj,
						params: urlParams,
						meta: modulaMetaVars,
					},
				})
			);
			// Reconstruct the URL with the updated parameters
			const newUrl =
				urlObj.origin +
				urlObj.pathname +
				'?' +
				decodeURIComponent(urlParams.toString());

			var email = plugin.options.email_message
				.replace('%%image_link%%', imageUrl)
				.replace('%%gallery_link%%', newUrl);

			var url =
				'mailto:?subject=' +
				encodeURIComponent(subject) +
				'&body=' +
				encodeURIComponent(email);

			var w = window.open(
				url,
				'ftgw',
				'location=1,status=1,scrollbars=1,width=600,height=400'
			);

			w.moveTo(screen.width / 2 - 300, screen.height / 2 - 200);
			return false;
		});
	};

	var setupSocials = function ($tiles) {
		$tiles.find('.jtg-social-expandable').on('click', function (e) {
			e.preventDefault();
			e.stopPropagation();

			var $parent = $(this).parent();
			var $icons = $parent.children('.jtg-social-expandable-icons');

			$tiles
				.find('.jtg-social-expandable-icons')
				.not($icons)
				.removeClass('modula-show-socials');

			$icons.toggleClass('modula-show-socials');

			if (
				$icons.hasClass('modula-show-socials') &&
				isElementOutOfHorizontalViewport($icons)
			) {
				$icons.addClass('modula-socials-right');
			} else {
				$icons.removeClass('modula-socials-right');
			}
		});
	};

	var isElementOutOfHorizontalViewport = function (el) {
		var rect = el[0].getBoundingClientRect();
		var windowWidth =
			window.innerWidth || document.documentElement.clientWidth;

		return rect.left < 0 || rect.right > windowWidth;
	};

	$.fn[pluginName] = function (options) {
		var args = arguments;

		if (options === undefined || typeof options === 'object') {
			return this.each(function () {
				if (!$.data(this, 'plugin_' + pluginName)) {
					$.data(
						this,
						'plugin_' + pluginName,
						new Plugin(this, options)
					);
				}
			});
		} else if (
			typeof options === 'string' &&
			options[0] !== '_' &&
			options !== 'init'
		) {
			var returns;

			this.each(function () {
				var instance = $.data(this, 'plugin_' + pluginName);

				// Tests that there's already a plugin-instance
				// and checks that the requested public method exists
				if (
					instance instanceof Plugin &&
					typeof instance[options] === 'function'
				) {
					// Call the method of our plugin instance,
					// and pass it the supplied arguments.
					returns = instance[options].apply(
						instance,
						Array.prototype.slice.call(args, 1)
					);
				}

				// Allow instances to be destroyed via the 'destroy' method
				if (options === 'destroy') {
					$.data(this, 'plugin_' + pluginName, null);
				}
			});

			return returns !== undefined ? returns : this;
		}
	};
})(jQuery, window, document);

jQuery(document).ready(function () {
	var modulaGalleries = jQuery('.modula.modula-gallery');
	if (!jQuery('body').hasClass('modula-best-grid-gallery')) {
		jQuery('body').addClass('modula-best-grid-gallery');
	}
	jQuery.each(modulaGalleries, function () {
		var modulaSettings = jQuery(this).data('config');
		jQuery(this).modulaGallery(modulaSettings);
	});
});

// initiliaza galleries that are in elementor popup
jQuery(document).on('elementor/popup/show', (event, id, instance) => {
	var modulaGalleries = jQuery('#elementor-popup-modal-' + id).find(
		'.modula.modula-gallery'
	);
	if (!jQuery('body').hasClass('modula-best-grid-gallery')) {
		jQuery('body').addClass('modula-best-grid-gallery');
	}
	jQuery.each(modulaGalleries, function () {
		var modulaSettings = jQuery(this).data('config');

		jQuery(this).modulaGallery(modulaSettings);
	});
});

// function to check if modula is in viewport
function modulaInViewport(element) {
	if (typeof jQuery === 'function' && element instanceof jQuery) {
		element = element[0];
	}

	var elementBounds = element.getBoundingClientRect();
	var winHeight = jQuery(window).height();

	return (
		(elementBounds.top - winHeight <= -100 &&
			elementBounds.top - winHeight >= -400) ||
		elementBounds.bottom <= winHeight ||
		(elementBounds.top < winHeight && elementBounds.bottom > 0)
	);
}
