import 'dart:convert'; import 'dart:io'; import 'package:cabo_counter/data/game_manager.dart'; import 'package:cabo_counter/data/game_session.dart'; import 'package:file_picker/file_picker.dart'; import 'package:file_saver/file_saver.dart'; import 'package:flutter/services.dart'; import 'package:json_schema/json_schema.dart'; import 'package:path_provider/path_provider.dart'; class LocalStorageService { static const String _fileName = 'game_data.json'; /// Writes the game session list to a JSON file and returns it as string. static String getJsonFile() { final jsonFile = gameManager.gameList.map((session) => session.toJson()).toList(); return json.encode(jsonFile); } /// Returns the path to the local JSON file. static Future _getFilePath() async { final directory = await getApplicationDocumentsDirectory(); final path = '${directory.path}/$_fileName'; return File(path); } /// Saves the game sessions to a local JSON file. static Future saveGameSessions() async { try { final file = await _getFilePath(); final jsonFile = getJsonFile(); await file.writeAsString(jsonFile); print( '[local_storage_service.dart] Die Spieldaten wurden zwischengespeichert.'); } catch (e) { print( '[local_storage_service.dart] Fehler beim Speichern der Spieldaten. Exception: $e'); } } /// Loads the game data from a local JSON file. static Future loadGameSessions() async { print('[local_storage_service.dart] Versuche, Daten zu laden...'); try { final file = await _getFilePath(); if (!await file.exists()) { print( '[local_storage_service.dart] Es existiert noch keine Datei mit Spieldaten'); return false; } print( '[local_storage_service.dart] Es existiert bereits eine Datei mit Spieldaten'); final jsonString = await file.readAsString(); if (jsonString.isEmpty) { print('[local_storage_service.dart] Die gefundene Datei ist leer'); return false; } if (!await validateJsonSchema(jsonString)) { print( '[local_storage_service.dart] Die Datei konnte nicht validiert werden'); gameManager.gameList = []; return false; } print('[local_storage_service.dart] Die gefundene Datei hat Inhalt'); print( '[local_storage_service.dart] Die gefundene Datei wurde erfolgreich validiert'); final jsonList = json.decode(jsonString) as List; gameManager.gameList = jsonList .map((jsonItem) => GameSession.fromJson(jsonItem as Map)) .toList(); print( '[local_storage_service.dart] Die Spieldaten wurden erfolgreich geladen und verarbeitet'); return true; } catch (e) { print( '[local_storage_service.dart] Fehler beim Laden der Spieldaten:\n$e'); gameManager.gameList = []; return false; } } /// Opens the file picker to save a JSON file with the current game data. static Future exportJsonFile() async { final jsonString = getJsonFile(); try { final bytes = Uint8List.fromList(utf8.encode(jsonString)); final result = await FileSaver.instance.saveAs( name: 'cabo_counter_data', bytes: bytes, ext: 'json', mimeType: MimeType.json, ); print( '[local_storage_service.dart] Die Spieldaten wurden exportiert. Dateipfad: $result'); return true; } catch (e) { print( '[local_storage_service.dart] Fehler beim Exportieren der Spieldaten. Exception: $e'); return false; } } /// Opens the file picker to import a JSON file and loads the game data from it. static Future importJsonFile() async { final result = await FilePicker.platform.pickFiles( dialogTitle: 'Wähle eine Datei mit Spieldaten aus', type: FileType.custom, allowedExtensions: ['json'], ); if (result == null) { print( '[local_storage_service.dart] Der Filepicker-Dialog wurde abgebrochen'); return false; } try { final jsonString = await _readFileContent(result.files.single); if (!await validateJsonSchema(jsonString)) { return false; } final jsonData = json.decode(jsonString) as List; gameManager.gameList = jsonData .map((jsonItem) => GameSession.fromJson(jsonItem as Map)) .toList(); print( '[local_storage_service.dart] Die Datei wurde erfolgreich Importiertn'); return true; } on FormatException catch (e) { print( '[local_storage_service.dart] Ungültiges JSON-Format. Exception: $e'); return false; } on Exception catch (e) { print( '[local_storage_service.dart] Fehler beim Dateizugriff. Exception: $e'); return false; } } /// Helper method to read file content from either bytes or path static Future _readFileContent(PlatformFile file) async { if (file.bytes != null) return utf8.decode(file.bytes!); if (file.path != null) return await File(file.path!).readAsString(); throw Exception('Die Datei hat keinen lesbaren Inhalt'); } /// Validates the JSON data against the schema. static Future validateJsonSchema(String jsonString) async { try { final schemaString = await rootBundle.loadString('assets/schema.json'); final schema = JsonSchema.create(json.decode(schemaString)); final jsonData = json.decode(jsonString); final result = schema.validate(jsonData); if (result.isValid) { print('[local_storage_service.dart] JSON ist erfolgreich validiert.'); return true; } print( '[local_storage_service.dart] JSON ist nicht gültig.\nFehler: ${result.errors}'); return false; } catch (e) { print( '[local_storage_service.dart] Fehler beim Validieren des JSON-Schemas: $e'); return false; } } static Future deleteAllGames() async { try { gameManager.gameList.clear(); await saveGameSessions(); print( '[local_storage_service.dart] Alle Runden wurden erfolgreich gelöscht.'); return true; } catch (e) { print( '[local_storage_service.dart] Fehler beim Löschen aller Runden: $e'); return false; } } }