using System.Drawing; using System.Globalization; using System.Xml.Linq; using MaddoShared; namespace CatalogLite; public sealed class CatalogConfigurationLoader { public CatalogLiteConfiguration Load(string filePath, PicSettings picSettings) { if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentException("Percorso configurazione non valido.", nameof(filePath)); } if (!File.Exists(filePath)) { throw new FileNotFoundException("File configurazione non trovato.", filePath); } var values = ConfigurationValues.Load(filePath); ApplyPicSettings(values, picSettings); var sourcePath = LiteCatalogViewModel.NormalizeDirectoryPath(values.GetString("DirSorgente")); var destinationPath = LiteCatalogViewModel.NormalizeDirectoryPath(values.GetString("DirDestinazione")); picSettings.DirectorySorgente = sourcePath; picSettings.DirectoryDestinazione = destinationPath; picSettings.DestDir = string.IsNullOrWhiteSpace(destinationPath) ? new DirectoryInfo(Environment.CurrentDirectory) : new DirectoryInfo(destinationPath); return new CatalogLiteConfiguration { FilePath = filePath, SourcePath = sourcePath, DestinationPath = destinationPath, Options = BuildOptions(values, sourcePath, destinationPath) }; } public static ImageCreationService.Options CloneOptions(ImageCreationService.Options options, string sourcePath, string destinationPath) { return new ImageCreationService.Options { AggiornaSottodirectory = options.AggiornaSottodirectory, CreaSottocartelle = options.CreaSottocartelle, FilePerCartella = options.FilePerCartella, SuffissoCartelle = options.SuffissoCartelle, CifreContatore = options.CifreContatore, NumerazioneType = options.NumerazioneType, SourcePath = sourcePath, DestinationPath = destinationPath, MaxThreads = Math.Max(1, options.MaxThreads), ChunksSize = options.ChunksSize, LinearExecution = options.LinearExecution }; } private static void ApplyPicSettings(ConfigurationValues values, PicSettings settings) { settings.DirectorySorgente = values.GetString("DirSorgente"); settings.DirectoryDestinazione = values.GetString("DirDestinazione"); settings.TestoFirmaStart = values.GetString("TestoTesto"); settings.TestoFirmaStartV = values.GetString("TestoVerticale"); settings.DataPartenza = values.GetDateTime("DataPartenza", DateTime.Now); settings.TestoOrario = values.GetString("EtichettaOrario"); settings.DimStandard = values.GetInt("FontDimensione", 20); settings.DimStandardMiniatura = values.GetInt("FontDimensioneMiniatura", 50); settings.NomeData = values.GetBool("DataFoto"); settings.TestoNome = values.GetBool("NumeroFoto"); settings.UsaOrarioMiniatura = IsThumbnailMode(values, "Time") || values.GetBool("MiniatureAddOrario"); settings.UsaOrarioTestoApplicare = values.GetBool("Orario"); settings.UsaTempoGaraTestoApplicare = values.GetBool("TempoGara"); settings.UsaRotazioneAutomatica = values.GetBool("GeneraleRotazioneAutomatica"); settings.UsaForzaJpg = values.GetBool("GeneraleForzaJpg"); settings.LarghezzaSmall = values.GetInt("MiniatureLarghezza", 350); settings.AltezzaSmall = values.GetInt("MiniatureAltezza", 350); settings.CreaMiniature = values.GetBool("MiniatureCrea", true); settings.AggiungiScritteMiniature = IsThumbnailMode(values, "Text") || values.GetBool("MiniatureAddScritta"); settings.Suffisso = values.GetString("MiniatureSuffisso", "tn_"); settings.Codice = values.GetString("FotoCodice"); settings.Trasparenza = values.GetInt("TestoTrasparente", 0); settings.IlFont = values.GetString("FontNome", "Arial"); settings.Grassetto = values.GetBool("FontBold"); settings.Posizione = values.GetString("TestoPosizione", "Basso"); settings.Allineamento = values.GetString("TestoAllineamento", "Centro"); settings.Margine = values.GetInt("TestoMargine", 8); settings.LogoAltezza = values.GetInt("MarchioAltezza", 430); settings.LogoLarghezza = values.GetInt("MarchioLarghezza", 430); settings.FontColoreRGB = ParseColor(values.GetString("ColoreTestoRGB", "Yellow"), Color.Yellow); settings.LogoAggiungi = values.GetBool("MarchioAggiungi"); settings.LogoNomeFile = values.GetString("MarchioFile"); settings.LogoTrasparenza = values.GetInt("MarchioTrasparenza", 100).ToString(CultureInfo.InvariantCulture); settings.LogoMargine = values.GetString("MarchioMargine", "0"); settings.LogoPosizioneH = values.GetString("MarchioAllOrizzontale", "Destra"); settings.LogoPosizioneV = values.GetString("MarchioAllVerticale", "Basso"); settings.TransparentColor = values.GetString("ColoreTrasparente", "#FFFFFF"); settings.UseTransparentColor = values.GetBool("UsaColoreTrasparente"); settings.FotoGrandeDimOrigina = values.GetBool("FotoDimOriginali"); settings.AltezzaBig = values.GetInt("FotoAltezza", 2240); settings.LarghezzaBig = values.GetInt("FotoLarghezza", 2240); settings.DimVert = values.GetInt("GrandezzaVerticale", 20); settings.MargVert = values.GetInt("MargineVerticale", 6); settings.TestoMin = IsThumbnailMode(values, "FileName") || values.GetBool("NomeMiniatura"); settings.DimMin = values.GetInt("FontDimensioneMiniatura", 50); settings.SecretDefault = false; settings.SecretBig = false; settings.SecretSmall = false; settings.SecretPathSmall = string.Empty; settings.SecretPathBig = string.Empty; settings.AggTempoGaraMin = IsThumbnailMode(values, "RaceTime") || values.GetBool("TempoSmall"); settings.AggNumTempMin = IsThumbnailMode(values, "FileNameAndTime") || values.GetBool("NumTempoSmall"); settings.JpegQuality = values.GetLong("CompressioneJpeg", 85); settings.JpegQualityMin = values.GetLong("CompressioneJpegMiniatura", 30); settings.FotoRuotaADestra = false; settings.FotoRuotaASinistra = false; settings.TempMinText = string.Empty; settings.OverwriteFiles = values.GetBool("GeneraleSovrascriviFile"); settings.ImageCreatorProvider = "ImageSharp"; } private static ImageCreationService.Options BuildOptions(ConfigurationValues values, string sourcePath, string destinationPath) { var threads = values.GetInt("ThreadsCount", Environment.ProcessorCount); if (threads <= 0) { threads = Environment.ProcessorCount; } return new ImageCreationService.Options { AggiornaSottodirectory = values.GetBool("DirSottoDirectory"), CreaSottocartelle = values.GetBool("DirCreaSottocartelle", values.GetBool("CreateSubfolders")), FilePerCartella = Math.Max(1, values.GetInt("DirDividiNumFile", 99)), SuffissoCartelle = values.GetString("DirDividiSuffisso"), CifreContatore = Math.Max(1, values.GetInt("DirDividiNumCifre", 2)), NumerazioneType = values.GetBool("DirNumerazioneProgressiva", true) ? NumerazioneType.Progressiva : NumerazioneType.Files, SourcePath = sourcePath, DestinationPath = destinationPath, MaxThreads = Math.Max(1, threads), ChunksSize = Math.Max(0, values.GetInt("ChunkSize", 0)), LinearExecution = values.GetBool("UseSequentialProcessing") }; } private static bool IsThumbnailMode(ConfigurationValues values, string mode) { return string.Equals(values.GetString("MiniatureModalita"), mode, StringComparison.OrdinalIgnoreCase); } private static Color ParseColor(string value, Color fallback) { if (string.IsNullOrWhiteSpace(value)) { return fallback; } var normalized = value.Trim(); try { if (normalized.StartsWith('#') && normalized.Length == 7) { return Color.FromArgb( Convert.ToInt32(normalized[1..3], 16), Convert.ToInt32(normalized[3..5], 16), Convert.ToInt32(normalized[5..7], 16)); } var named = Color.FromName(normalized); return named.IsKnownColor || named.IsNamedColor ? named : fallback; } catch { return fallback; } } private sealed class ConfigurationValues { private readonly Dictionary _values; private ConfigurationValues(Dictionary values) { _values = values; } public static ConfigurationValues Load(string filePath) { var document = XDocument.Load(filePath); var values = document .Descendants("Setup") .Where(element => element.Element("Nome") is not null) .GroupBy(element => element.Element("Nome")!.Value, StringComparer.OrdinalIgnoreCase) .ToDictionary( group => group.Key, group => group.Last().Element("Valore")?.Value ?? string.Empty, StringComparer.OrdinalIgnoreCase); if (values.Count == 0) { values = document.Root? .Descendants() .Where(element => !element.HasElements) .GroupBy(element => element.Name.LocalName, StringComparer.OrdinalIgnoreCase) .ToDictionary(group => group.Key, group => group.Last().Value, StringComparer.OrdinalIgnoreCase) ?? new Dictionary(StringComparer.OrdinalIgnoreCase); } return new ConfigurationValues(values); } public string GetString(string name, string defaultValue = "") { return _values.TryGetValue(name, out var value) && !string.IsNullOrWhiteSpace(value) ? value.Trim() : defaultValue; } public bool GetBool(string name, bool defaultValue = false) { var value = GetString(name); if (string.IsNullOrWhiteSpace(value)) { return defaultValue; } return value.Trim().ToUpperInvariant() switch { "TRUE" or "OK" or "SI" or "SÌ" or "1" or "YES" or "VERO" => true, "FALSE" or "NO" or "0" or "FALSO" => false, _ => defaultValue }; } public int GetInt(string name, int defaultValue = 0) { return int.TryParse(GetString(name), NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : defaultValue; } public long GetLong(string name, long defaultValue = 0) { return long.TryParse(GetString(name), NumberStyles.Integer, CultureInfo.InvariantCulture, out var value) ? value : defaultValue; } public DateTime GetDateTime(string name, DateTime defaultValue) { var value = GetString(name); if (DateTime.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var invariantDate)) { return invariantDate; } return DateTime.TryParse(value, CultureInfo.CurrentCulture, DateTimeStyles.AssumeLocal, out var localDate) ? localDate : defaultValue; } } }