using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Project_Periodensystem.Model;
namespace Project_Periodensystem.Persistence
{
///
/// Zentrale Persistenz-Schicht für JSON-basierte Datenspeicherung
///
/// ZWECK UND ARCHITEKTUR:
/// - Abstrahiert Datei-I/O von der Geschäftslogik (Separation of Concerns)
/// - Implementiert Repository Pattern für Element- und Settings-Daten
/// - Bietet Fallback-Mechanismus für robuste Datenversorgung
/// - Demonstriert moderne .NET JSON-Serialisierung
///
/// DESIGN PATTERNS:
/// - Repository Pattern: Zentrale Datenquelle mit einheitlicher API
/// - Static Class: Globaler Zugriff ohne Instanziierung
/// - Fallback Strategy: Graceful Degradation bei fehlenden Dateien
/// - Factory Pattern: Erstellt Default-Objekte wenn nötig
///
/// C# KONZEPTE:
/// - System.Text.Json: Modernes JSON-Framework (.NET Core/5+)
/// - JsonSerializerOptions: Konfiguration der JSON-Ausgabe
/// - Generic Methods: Wiederverwendbare Serialisierung für verschiedene Typen
/// - Exception Handling: Robuste Fehlerbehandlung bei I/O-Operationen
/// - Null-Coalescing (??): Fallback-Werte bei null-Objekten
///
/// DATENSPEICHERUNG:
/// - LocalApplicationData: Benutzer-spezifische, nicht-roaming Daten
/// - JSON Format: Menschenlesbar, plattformunabhängig, einfach zu debuggen
/// - Strukturierte Verzeichnisse: Organisierte Dateiablage
///
public static class DataManager
{
// ===== PFAD-KONFIGURATION =====
///
/// Basis-Verzeichnis für alle Anwendungsdaten
///
/// PFAD-STRATEGIEN:
/// - LocalApplicationData: Benutzer-spezifisch, lokal (nicht synchronisiert)
/// - Windows: C:\Users\[Username]\AppData\Local\Periodensystem\
/// - Cross-Platform: Funktioniert auf Windows, Linux, macOS
///
/// VORTEILE:
/// - Keine Admin-Rechte erforderlich
/// - Benutzer-spezifische Isolation
/// - Standard-Konformität mit OS-Richtlinien
///
private static readonly string DataDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Periodensystem");
///
/// Vollständiger Pfad zur Element-Datenbasis (JSON)
/// Speichert alle chemischen Elemente mit ihren Eigenschaften
///
private static readonly string ElementsFile = Path.Combine(DataDirectory, "elements.json");
///
/// Vollständiger Pfad zu Benutzereinstellungen (JSON)
/// Speichert Präferenzen wie Theme, Sprache, letzte Nutzung
///
private static readonly string SettingsFile = Path.Combine(DataDirectory, "settings.json");
// ===== ELEMENT-DATEN PERSISTENZ =====
///
/// Speichert eine Element-Liste als JSON-Datei
///
/// ZWECK:
/// - Persistierung von benutzerdefinierten oder bearbeiteten Elementen
/// - Backup von Element-Daten für Wiederherstellung
/// - Export-Funktionalität für Datenübertragung
///
/// C# KONZEPTE:
/// - JsonSerializer.Serialize(): Moderne .NET JSON-Serialisierung
/// - JsonSerializerOptions: Konfiguration der JSON-Ausgabe
/// - WriteIndented: Menschenlesbare Formatierung (Pretty-Print)
/// - Directory.CreateDirectory(): Erstellt Verzeichnis-Hierarchie falls nötig
/// - File.WriteAllText(): Atomare Datei-Schreiboperation
///
/// FEHLERBEHANDLUNG:
/// - Try-Catch um gesamte Operation
/// - Logging aller Erfolgs- und Fehlerfälle
/// - Graceful Degradation: Anwendung funktioniert ohne Persistenz
///
/// JSON-AUSGABE:
/// - Eingerückt und formatiert für manuelle Bearbeitung
/// - UTF-8 Encoding für internationale Zeichen
/// - Standard JSON-Format für Interoperabilität
///
/// Liste der zu speichernden Elemente
public static void SaveElements(List elements)
{
try
{
// Verzeichnis erstellen falls nicht vorhanden
Directory.CreateDirectory(DataDirectory);
// JSON-Serialisierung mit lesbarer Formatierung
var json = JsonSerializer.Serialize(elements, new JsonSerializerOptions { WriteIndented = true });
// Atomare Datei-Operation (ersetzt bestehende Datei)
File.WriteAllText(ElementsFile, json);
Logger.Log($"Elemente erfolgreich gespeichert: {elements.Count} Einträge in {ElementsFile}");
}
catch (Exception ex)
{
Logger.LogException(ex, "SaveElements");
// Keine Weiterleitung der Exception - Speichern ist optional
}
}
///
/// Lädt Elemente aus JSON-Datei mit Fallback zu eingebauten Daten
///
/// ZWECK:
/// - Primäre Datenquelle für alle Element-Informationen
/// - Robuste Datenversorgung durch Fallback-Mechanismus
/// - Unterstützung für persistierte Benutzeränderungen
///
/// FALLBACK-STRATEGIE:
/// 1. Versuche JSON-Datei zu laden (benutzerdefinierte Daten)
/// 2. Bei Fehlern: Fallback zu PeriodicTableData.Elements (eingebaute Daten)
/// 3. Garantiert immer eine funktionsfähige Element-Liste
///
/// C# KONZEPTE:
/// - JsonSerializer.Deserialize<T>(): Generische Deserialisierung
/// - File.Exists(): Existenz-Prüfung vor Dateizugriff
/// - Null-Conditional Check: elements != null && elements.Count > 0
/// - Multiple Return Points: Verschiedene Ausstiegspunkte je nach Szenario
///
/// FEHLERBEHANDLUNG:
/// - Alle I/O-Operationen in try-catch
/// - Validierung der deserialisierten Daten
/// - Logging aller Ladeschritte für Debugging
/// - Graceful Fallback ohne Exception-Weiterleitung
///
/// Liste aller verfügbaren chemischen Elemente
public static List LoadElements()
{
try
{
// Prüfung ob benutzerdefinierte Daten existieren
if (File.Exists(ElementsFile))
{
var json = File.ReadAllText(ElementsFile);
var elements = JsonSerializer.Deserialize>(json);
// Validierung der deserialisierten Daten
if (elements != null && elements.Count > 0)
{
Logger.Log($"Elemente aus benutzerdefinierter Datei geladen: {elements.Count} Einträge");
return elements;
}
}
}
catch (Exception ex)
{
Logger.LogException(ex, "LoadElements - JSON Loading");
// Kein Re-throw - Fallback folgt
}
// Fallback zu eingebauten, statischen Daten
Logger.Log("Fallback zu eingebauten Element-Daten (PeriodicTableData)");
return PeriodicTableData.Elements;
}
// ===== BENUTZEREINSTELLUNGEN PERSISTENZ =====
///
/// Speichert Benutzereinstellungen als JSON-Datei
///
/// ZWECK:
/// - Persistierung von Benutzer-Präferenzen zwischen App-Sessions
/// - Theme-Einstellungen, Sprach-Präferenzen, etc. speichern
/// - Personalisierte Benutzererfahrung ermöglichen
///
/// C# KONZEPTE:
/// - Gleiche JSON-Serialisierung wie bei Elementen
/// - Konsistente Fehlerbehandlung und Logging
/// - Atomare Datei-Operationen für Datenintegrität
///
/// SETTINGS-BEISPIELE:
/// - UI Theme (Light/Dark)
/// - Bevorzugte Sprache
/// - Letzte Nutzung (für Statistiken)
/// - Personalisierte Element-Ansichten
///
/// AppSettings-Objekt mit Benutzer-Präferenzen
public static void SaveSettings(AppSettings settings)
{
try
{
// Verzeichnis sicherstellen (gleich wie bei Elementen)
Directory.CreateDirectory(DataDirectory);
// JSON-Serialisierung mit Pretty-Print
var json = JsonSerializer.Serialize(settings, new JsonSerializerOptions { WriteIndented = true });
// Atomare Speicherung
File.WriteAllText(SettingsFile, json);
Logger.Log($"Benutzereinstellungen gespeichert: Theme={settings.LastTheme}, Sprache={settings.PreferredLanguage}");
}
catch (Exception ex)
{
Logger.LogException(ex, "SaveSettings");
// Keine Exception-Weiterleitung - Settings sind optional
}
}
///
/// Lädt Benutzereinstellungen aus JSON-Datei
///
/// ZWECK:
/// - Wiederherstellung der Benutzer-Präferenzen beim App-Start
/// - Fallback zu Default-Settings bei fehlender oder korrupter Datei
/// - Konsistente Benutzererfahrung über Sessions hinweg
///
/// FALLBACK-VERHALTEN:
/// - Bei fehlender Datei: Neue AppSettings() mit Defaults
/// - Bei JSON-Fehlern: Neue AppSettings() mit Defaults
/// - Garantiert immer gültige Settings-Objekt
///
/// C# KONZEPTE:
/// - Null-Coalescing Operator (??): settings ?? new AppSettings()
/// - Constructor mit Default-Werten in AppSettings
/// - Robuste Deserialisierung mit Fallback
///
/// AppSettings-Objekt (entweder geladen oder mit Defaults)
public static AppSettings LoadSettings()
{
try
{
if (File.Exists(SettingsFile))
{
var json = File.ReadAllText(SettingsFile);
var settings = JsonSerializer.Deserialize(json);
// Null-Coalescing für sichere Rückgabe
var result = settings ?? new AppSettings();
Logger.Log($"Benutzereinstellungen geladen: Theme={result.LastTheme}");
return result;
}
}
catch (Exception ex)
{
Logger.LogException(ex, "LoadSettings");
// Kein Re-throw - Fallback zu Defaults
}
// Fallback zu Default-Settings
Logger.Log("Fallback zu Standard-Benutzereinstellungen");
return new AppSettings();
}
}
///
/// Datenmodell für persistierte Benutzereinstellungen
///
/// ZWECK UND STRUKTUR:
/// - Kapselt alle persistierbaren Benutzer-Präferenzen
/// - Einfache Erweiterung um neue Settings möglich
/// - JSON-serialisierbar durch Auto-Properties
/// - Default-Werte für robuste Initialisierung
///
/// DESIGN PRINCIPLES:
/// - Data Transfer Object (DTO): Reine Datenklasse
/// - Default Values: Sinnvolle Startwerte für neue Installationen
/// - Extensibility: Einfache Erweiterung um neue Properties
/// - Immutable nach Konstruktion: Properties könnten readonly sein
///
/// C# KONZEPTE:
/// - Auto-Properties mit Default-Initialisierung
/// - DateTime für Zeitstempel
/// - String-Properties für einfache Serialisierung
/// - Parameterloser Constructor (implizit für JSON-Deserialisierung)
///
/// JSON-SERIALISIERUNG:
/// - Alle Properties werden automatisch serialisiert
/// - Property-Namen werden als JSON-Keys verwendet
/// - Default-Werte sorgen für robuste Deserialisierung
///
public class AppSettings
{
///
/// Zuletzt verwendetes UI-Theme
///
/// WERTE:
/// - "Light": Helles Theme für Tag-Nutzung
/// - "Dark": Dunkles Theme für augen-schonende Nutzung
/// - "Auto": System-Theme folgen (Windows/macOS)
///
/// DEFAULT: "Dark" - Moderner Standard für Entwicklungs-Tools
///
public string LastTheme { get; set; } = "Dark";
///
/// Zeitstempel der letzten Anwendungsnutzung
///
/// ZWECK:
/// - Nutzungsstatistiken
/// - "Willkommen zurück"-Funktionen
/// - Data Analytics für Verbesserungen
///
/// DEFAULT: DateTime.Now - Aktueller Zeitpunkt bei Erstellung
///
public DateTime LastUsed { get; set; } = DateTime.Now;
///
/// Bevorzugte Sprache der Benutzeroberfläche
///
/// WERTE:
/// - "German": Deutsche Lokalisierung
/// - "English": Englische Lokalisierung
/// - "French": Französische Lokalisierung (wenn implementiert)
///
/// DEFAULT: "German" - Da es ein deutsches Lernprojekt ist
///
public string PreferredLanguage { get; set; } = "German";
}
}