@inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel>
@using Dynamicweb.Ecommerce.ProductCatalog
@using Dynamicweb.Frontend
@using System.IO
@using System.Text.RegularExpressions;

@functions {
	public ProductViewModel product { get; set; } = new ProductViewModel();
	public string galleryLayout { get; set; }
	public string[] supportedImageFormats { get; set; }
	public string[] supportedVideoFormats { get; set; }
	public string[] supportedDocumentFormats { get; set; }
	public string[] allSupportedFormats { get; set; }

	public class RatioSettings
	{
		public string Ratio { get; set; }
		public string CssClass { get; set; }
		public string CssVariable { get; set; }
		public string Fill { get; set; }
	}

	public RatioSettings GetRatioSettings(string size = "desktop")
	{
		var ratioSettings = new RatioSettings();

		string ratio = Model.Item.GetRawValueString("ImageAspectRatio", "");
		ratio = ratio != "0" ? ratio : "";
		string cssClass = ratio != "" && ratio != "fill" ? " ratio" : "";
		string cssVariable = ratio != "" && ratio != "fill" ? "--bs-aspect-ratio: " + ratio : "";
		cssClass = ratio == "fill" && size == "mobile" ? " ratio" : cssClass;
		cssVariable = ratio == "fill" && size == "mobile" ? "--bs-aspect-ratio: 66%" : cssVariable;

		ratioSettings.Ratio = ratio;
		ratioSettings.CssClass = cssClass;
		ratioSettings.CssVariable = cssVariable;
		ratioSettings.Fill = ratio == "fill" ? " h-100" : "";

		return ratioSettings;
	}

	public string GetArrowsColor()
	{
		var invertColor = Model.Item.GetBoolean("InvertModalArrowsColor");
		var arrowsColor = invertColor ? " carousel-dark" : string.Empty;
		return arrowsColor;
	}

	public string GetThumbnailPlacement()
	{
		return Model.Item.GetRawValueString("ThumbnailPlacement", "bottom");
	}

	public string GetThumbnailRowSettingCss()
	{
		switch (GetThumbnailPlacement())
		{
			case "bottom":
				return "d-flex flex-wrap";
			case "left":
				return "d-flex flex-column order-first";
			case "right":
				return "d-flex flex-column order-last";
			default:
				return "d-flex flex-wrap";
		}
	}

	public string GetVideoType(string assetValue)
	{
		string type = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "youtube" : string.Empty;
		type = assetValue.IndexOf("vimeo", StringComparison.OrdinalIgnoreCase) >= 0 ? "vimeo" : type;
		type = string.IsNullOrEmpty(type) ? "selfhosted" : type;
		
		return type;
	}

	public string GetYoutubeScreenDump(string assetValue, string quality)
	{
		var regex = new Regex(@"(?:youtube\.com\/.*[\?&]v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)(?:\?.*)?");
		Match match = regex.Match(assetValue);
		string videoId = match.Success ? match.Groups[1].Value : string.Empty;
		string youtubeThumbnail = $"https://img.youtube.com/vi/{videoId}/{quality}.jpg";
		return youtubeThumbnail;
	}

	public string GetFileTypeIcon(string filePath)
	{
		string fileType = Path.GetExtension(filePath).ToLower();
		string fileTypeIconPath = "/Files/Templates/Designs/Swift-v2/Assets/images/FileTypes/";
		var iconMap = new Dictionary<string, string>
		{
			{ ".pdf", $"{fileTypeIconPath}pdf.svg" },
			{ ".docx", $"{fileTypeIconPath}docx.svg" },
			{ ".xlsx", $"{fileTypeIconPath}xlsx.svg" },
			{ ".ppt", $"{fileTypeIconPath}ppt.svg" }
		};
		return iconMap.ContainsKey(fileType) ? iconMap[fileType] : $"/Files/Images/Icons/download.svg";
	}

	public bool MatchesFormat(string assetValue, string[] formats)
	{
		return formats.Any(format => assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0);
	}
}

@{
	ProductViewModel product = null;
	if (Dynamicweb.Context.Current.Items.Contains("ProductDetails"))
	{
		product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"];
	}
}

@if (product is object)
{
	@* Supported formats *@
	supportedImageFormats = new string[] { ".jpg", ".jpeg", ".webp", ".png", ".gif", ".bmp", ".tiff" };
	supportedVideoFormats = new string[] { "youtu.be", "youtube", "vimeo", ".mp4", ".webm" };
	supportedDocumentFormats = new string[] { ".pdf", ".docx", ".xlsx", ".ppt", "pptx" };
	allSupportedFormats = supportedImageFormats.Concat(supportedVideoFormats).Concat(supportedDocumentFormats).ToArray();

	@* Collect the assets *@
	var selectedAssetCategories = Model.Item.GetList("ImageAssets")?.GetRawValue().OfType<string>();
	bool includeImagePatternImages = Model.Item.GetBoolean("ImagePatternImages");

	@* Needed image data collection to support both DefaultImage, ImagePatterns and Image Assets *@
	string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : "";
	IEnumerable<MediaViewModel> assetsImages = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets);
	assetsImages = assetsImages.OrderByDescending(x => x.Value.Equals(defaultImage));
	IEnumerable<MediaViewModel> assetsList = new MediaViewModel[] { };
	assetsList = assetsList.Union(assetsImages);
	assetsList = includeImagePatternImages ? assetsList.Union(product.ImagePatternImages) : assetsList;
	assetsList = includeImagePatternImages && assetsList.Count() == 0 ? assetsList.Append(product.DefaultImage) : assetsList;

	bool defaultImageFallback = Model.Item.GetBoolean("DefaultImageFallback");
	bool showOnlyPrimaryImage = Model.Item.GetBoolean("ShowOnlyPrimaryImage");

	int totalAssets = 0;
	if (showOnlyPrimaryImage == false)
	{
		totalAssets = assetsList.Count(asset => MatchesFormat(asset.Value, allSupportedFormats));
	}

	if ((totalAssets == 0 && product.DefaultImage != null && selectedAssetCategories.Count() == 0) || (showOnlyPrimaryImage == true && product.DefaultImage != null) || totalAssets == 0 && defaultImageFallback)
	{
		assetsList = new List<MediaViewModel>() { product.DefaultImage };
		totalAssets = 1;
	}

	@* Get assets from selected categories or get all assets *@
	if (totalAssets != 0)
	{
		int assetNumber = 0;
		int thumbnailNumber = 0;
		int modalAssetNumber = 0;
		string thumbnailAxisCss = GetThumbnailPlacement() == "bottom" ? "flex-column" : string.Empty;

		<div class="d-flex gap-3 h-100 @(thumbnailAxisCss) item_@Model.Item.SystemName.ToLower()" data-dw-colorscheme="@Model.ColorScheme?.Id">
			<div id="SmallScreenImages_@Model.ID" class="carousel@(GetArrowsColor()) col position-relative" data-bs-ride="carousel">
				<div class="carousel-inner h-100">
					@foreach (MediaViewModel asset in assetsList)
					{
						var assetValue = asset.Value;
						foreach (string format in allSupportedFormats)
						{
							if (assetValue.IndexOf(format, StringComparison.OrdinalIgnoreCase) >= 0)
							{
								string activeSlide = assetNumber == 0 ? "active" : "";

								<div class="carousel-item @activeSlide" data-bs-interval="99999">
									@{
										string size = "mobile";

										<div class="h-100">
											@foreach (string imageFormat in supportedImageFormats)
											{ //Images
												if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0)
												{
													if (product is object)
													{
														string productName = product.Name;
														string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value;

														RatioSettings ratioSettings = GetRatioSettings(size);

														var parms = new Dictionary<string, object>();
														parms.Add("alt", productName + asset.Keywords);
														parms.Add("itemprop", "image");
														parms.Add("columns", Model.GridRowColumnCount);
														parms.Add("eagerLoadNewImages", Model.Item.GetBoolean("DisableLazyLoading"));
														parms.Add("doNotUseGetimage", Model.Item.GetBoolean("DisableGetImage"));
														if (!string.IsNullOrEmpty(asset.DisplayName))
														{
															parms.Add("title", asset.DisplayName);
														}

														if (ratioSettings.Ratio == "fill" && galleryLayout != "grid")
														{
															parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover");
														}
														else
														{
															parms.Add("cssClass", "mw-100 mh-100");
														}

														<a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID">
															<div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@assetNumber">
																@RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms)
															</div>
														</a>
													}
												}
											}
											@foreach (string videoFormat in supportedVideoFormats)
											{ //Videos
												if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0)
												{
													if (product is object) {
														var video = asset.GetVideoViewModel();

														if (Model.Item.GetString("OpenVideoInModal") == "true")
														{
															string iconPath = "/Files/Images/Icons/";
															
															string productName = product.Name;
															productName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : "";
															string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? "title=\"" + asset.DisplayName + "\"" : "";

															RatioSettings ratioSettings = GetRatioSettings(size);
															
															string type = GetVideoType(asset.Value);

															string videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "maxresdefault") : string.Empty;
															string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : "";
															

															<div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable); cursor: pointer" data-bs-toggle="modal" data-bs-target="#modal_@Model.ID">
																<div class="d-flex align-items-center justify-content-center overflow-hidden h-100" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide-to="@assetNumber">
																	<div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div>
																	@if (video.IsExternalLink())
																	{
																		<img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@productName" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;">
																	}
																	else
																	{
																		
																		<video preload="auto" class="h-100 w-100" style="object-fit: contain;">
																			<source src="@(asset.Value)#t=0.001" type="@video.GetVideoType()">
																		</video>
																	}
																</div>
															</div>
														}
														else
														{
															@RenderPartial("Components/VideoPlayer.cshtml", video)
														}
													}
												}
											}
											@foreach (string documentFormat in supportedDocumentFormats)
											{ //Documents
												if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0)
												{
													if (product is object)
													{
														string productName = product.Name;
														string imagePath = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value;
														string fileTypeIcon = GetFileTypeIcon(asset.Value);

														RatioSettings ratioSettings = GetRatioSettings(size);

														var parms = new Dictionary<string, object>();
														parms.Add("alt", productName + asset.Keywords);
														parms.Add("itemprop", "image");
														parms.Add("fullwidth", true);
														parms.Add("columns", Model.GridRowColumnCount);

														if (!string.IsNullOrEmpty(asset.DisplayName))
														{
															parms.Add("title", asset.DisplayName);
														}

														if (ratioSettings.Ratio == "fill" && galleryLayout != "grid")
														{
															parms.Add("cssClass", "w-100 h-100 image-zoom-lg-l-hover");
														}
														else
														{
															parms.Add("cssClass", "mw-100 mh-100");
														}

														<a href="@imagePath" class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)" download title="@Translate("Download"): @(asset.Name)@Path.GetExtension(asset.Value).ToLower()">
															<div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border">
																<div class="icon-5 position-absolute" style="z-index: 1">
																	@ReadFile(fileTypeIcon)
																</div>
															</div>
														</a>
													}

												}
											}
										</div>
									}


								</div>
								assetNumber++;
							}
						}
					}
				</div>

			</div>

			@if (totalAssets > 1)
			{
				<div class="@(GetThumbnailRowSettingCss()) gap-3" id="SmallScreenImagesThumbnails_@Model.ID">
					@foreach (MediaViewModel asset in assetsList)
					{
						var assetValue = asset.Value;
						string assetName = asset.Name;
						assetName += !string.IsNullOrEmpty(asset.Keywords) ? " " + asset.Keywords : "";
						string assetTitle = !string.IsNullOrEmpty(asset.DisplayName) ? asset.DisplayName : null;									
						string iconPath = "/Files/Images/Icons/";
						
						string imagePath = assetValue;
						imagePath = assetValue.IndexOf("youtu.be", StringComparison.OrdinalIgnoreCase) >= 0 || assetValue.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) >= 0 ? "https://img.youtube.com/vi/" + assetValue.Substring(assetValue.LastIndexOf('/') + 1) + "/mqdefault.jpg" : imagePath;
						string imagePathThumb = assetValue.StartsWith("/Files/", StringComparison.OrdinalIgnoreCase) ? imagePath.IndexOf("youtube", StringComparison.OrdinalIgnoreCase) < 0 && imagePath.IndexOf(".mp4", StringComparison.OrdinalIgnoreCase) < 0 ? $"/Admin/Public/GetImage.ashx?image={imagePath}&width=180&format=webp" : imagePath : assetValue;

						RatioSettings ratioSettings = GetRatioSettings("desktop");
						
						<div class="border outline-none position-relative flex-grow-0 flex-shrink-0 @(ratioSettings.CssClass)" style="@(ratioSettings.CssVariable); cursor: pointer; width: clamp(4.5rem, 18vw, 8rem);" data-bs-target="#SmallScreenImages_@Model.ID" data-bs-slide-to="@thumbnailNumber">
							@foreach (string imageFormat in supportedImageFormats)
							{ //Images
								if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0)
								{
									<img src="@imagePathThumb" alt="@assetName" class="p-0 p-lg-1 w-100 h-100" style="object-fit: contain;">
								
									thumbnailNumber++;
								}
							}

							@foreach (string videoFormat in supportedVideoFormats)
							{ //Videos
								if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0)
								{
									var video = asset.GetVideoViewModel();
									string type = GetVideoType(asset.Value);

									string videoScreendumpPath = type == "youtube" ? GetYoutubeScreenDump(asset.Value, "mqdefault") : "";
									videoScreendumpPath = type == "vimeo" ? string.Empty : videoScreendumpPath;
									string videoJsClass = type == "vimeo" ? "js-vimeo-video-thumbnail" : string.Empty;

									<div class="icon-5 position-absolute top-50 start-50 translate-middle" style="z-index: 1">@ReadFile(iconPath + "play-circle.svg")</div>
									
									if (video.IsExternalLink())
									{
										<img src="@videoScreendumpPath" loading="lazy" decoding="async" alt="@assetTitle" @assetTitle class="@videoJsClass mw-100 mh-100" data-asset-value="@asset.Value" style="object-fit: cover;" />
									}
									else
									{
										<video preload="auto" class="h-100 w-100" style="object-fit: contain;">
											<source src="@(asset.Value)#t=0.001" type="@video.GetVideoType()">
										</video>
									}

									thumbnailNumber++;
								}
							}

							@foreach (string documentFormat in supportedDocumentFormats)
							{ //Documents
								if (assetValue.IndexOf(documentFormat, StringComparison.OrdinalIgnoreCase) >= 0)
								{
									string fileTypeIcon = GetFileTypeIcon(asset.Value);

									<a href="@assetValue" class="ratio ratio-4x3 border outline-none" style="cursor: pointer; min-width: 4rem; max-width: 8rem;" download title="@Translate("Download"): @(asset.Name)@Path.GetExtension(asset.Value).ToLower()">
										<div class="d-flex align-items-center justify-content-center text-center overflow-hidden h-100 border">
											<div class="icon-5 position-absolute" style="z-index: 1">@ReadFile(fileTypeIcon)</div>
										</div>
									</a>

									thumbnailNumber++;
								}
							}
						</div>
					}
				</div>
			}
		</div>

		@* Modal with slides *@
		<div class="modal fade" id="modal_@Model.ID" tabindex="-1" aria-labelledby="mediaModalTitle_@Model.ID" aria-hidden="true">
			<div class="modal-dialog modal-dialog-centered modal-xl">
				<div class="modal-content">
					<div class="modal-header visually-hidden">
						<h5 class="modal-title" id="mediaModalTitle_@Model.ID">@product.Title</h5>
						<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
					</div>
					<div class="modal-body p-2 p-lg-3 h-100">
						<div id="ModalCarousel_@Model.ID" class="carousel@(GetArrowsColor()) h-100" data-bs-ride="carousel">
							<div class="carousel-inner h-100" data-dw-colorscheme="@Model.ColorScheme?.Id">
								@foreach (MediaViewModel asset in assetsList)
								{
									var assetValue = !string.IsNullOrEmpty(asset.Value) ? asset.Value : product.DefaultImage.Value;
									foreach (string supportedFormat in supportedImageFormats.Concat(supportedVideoFormats).ToArray())
									{
										if (assetValue.IndexOf(supportedFormat, StringComparison.OrdinalIgnoreCase) >= 0)
										{
											string imagePath = assetValue;
											string activeSlide = modalAssetNumber == 0 ? "active" : "";

											var parms = new Dictionary<string, object>();
											parms.Add("cssClass", "d-block mw-100 mh-100 m-auto");
											parms.Add("fullwidth", true);
											parms.Add("columns", Model.GridRowColumnCount);

											<div class="carousel-item @activeSlide h-100" data-bs-interval="99999">
												@foreach (string imageFormat in supportedImageFormats)
												{ //Images
													if (assetValue.IndexOf(imageFormat, StringComparison.OrdinalIgnoreCase) >= 0)
													{
														@RenderPartial("Components/Image.cshtml", new FileViewModel { Path = imagePath }, parms)
													}
												}

												@foreach (string videoFormat in supportedVideoFormats)
												{ //Videos
													if (assetValue.IndexOf(videoFormat, StringComparison.OrdinalIgnoreCase) >= 0)
													{
														@RenderPartial("Components/VideoPlayer.cshtml", asset.GetVideoViewModel())
													}
												}
											</div>
											modalAssetNumber++;
										}
									}
								}
								<button class="carousel-control-prev carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="prev">
									<span class="carousel-control-prev-icon" aria-hidden="true"></span>
									<span class="visually-hidden">@Translate("Previous")</span>
								</button>
								<button class="carousel-control-next carousel-control-area" type="button" data-bs-target="#ModalCarousel_@Model.ID" data-bs-slide="next">
									<span class="carousel-control-next-icon" aria-hidden="true"></span>
									<span class="visually-hidden">@Translate("Next")</span>
								</button>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	}
	else if (Pageview.IsVisualEditorMode)
	{
		RatioSettings ratioSettings = GetRatioSettings("desktop");

		<div class="h-100" data-dw-colorscheme="@Model.ColorScheme?.Id">
			<div class="d-block @(ratioSettings.CssClass)@(ratioSettings.Fill)" style="@(ratioSettings.CssVariable)">
				<img src="/Files/Images/nopic.png" loading="lazy" decoding="async" class="mh-100 mw-100" style="object-fit: cover;">
			</div>
		</div>
	}
}
else if (Pageview.IsVisualEditorMode)
{
	<div class="alert alert-dark m-0">@Translate("The images will be shown here, if any")</div>
}



