import 'dart:convert'; import 'dart:io'; import 'package:flutter/services.dart'; import 'package:logger/logger.dart'; import '../domain/entities/function_button_config.dart'; import '../domain/entities/server_config.dart'; /// Application configuration loaded from servers.json class AppConfig { final List servers; final String coordinatorUrl; final String keyboardId; final FunctionButtonConfig functionButtons; final int alarmSyncIntervalSeconds; final int connectionRetrySeconds; final int commandTimeoutSeconds; const AppConfig({ required this.servers, this.coordinatorUrl = 'http://localhost:8090', this.keyboardId = 'keyboard-1', this.functionButtons = const FunctionButtonConfig(), this.alarmSyncIntervalSeconds = 30, this.connectionRetrySeconds = 5, this.commandTimeoutSeconds = 10, }); /// Load configuration from file or assets static Future load({String? configPath}) async { final logger = Logger(); Map configJson; // Try loading from file path first if (configPath != null) { try { final file = File(configPath); if (await file.exists()) { final contents = await file.readAsString(); configJson = jsonDecode(contents) as Map; logger.i('Loaded config from: $configPath'); return _parseConfig(configJson); } } catch (e) { logger.w('Failed to load config from file: $e'); } } // Try common file locations final commonPaths = [ 'servers.json', '../servers.json', 'config/servers.json', r'C:\DEV\COPILOT_D6\servers.json', ]; for (final path in commonPaths) { try { final file = File(path); if (await file.exists()) { final contents = await file.readAsString(); configJson = jsonDecode(contents) as Map; logger.i('Loaded config from: $path'); return _parseConfig(configJson); } } catch (e) { // Continue to next path } } // Try loading from assets try { final contents = await rootBundle.loadString('assets/config/servers.json'); configJson = jsonDecode(contents) as Map; logger.i('Loaded config from assets'); return _parseConfig(configJson); } catch (e) { logger.w('Failed to load config from assets: $e'); } // Return default empty config logger.w('No config file found, using defaults'); return const AppConfig(servers: []); } static AppConfig _parseConfig(Map json) { final serversJson = json['servers'] as List? ?? []; final servers = serversJson .map((s) => ServerConfig.fromJson(s as Map)) .where((s) => s.enabled) .toList(); final settings = json['settings'] as Map? ?? {}; // Parse function button config final fbJson = json['functionButtons'] as Map?; final functionButtons = fbJson != null ? FunctionButtonConfig.fromJson(fbJson) : const FunctionButtonConfig(); return AppConfig( servers: servers, coordinatorUrl: settings['coordinatorUrl'] as String? ?? 'http://localhost:8090', keyboardId: settings['keyboardId'] as String? ?? 'keyboard-1', functionButtons: functionButtons, alarmSyncIntervalSeconds: settings['alarmSyncIntervalSeconds'] as int? ?? 30, connectionRetrySeconds: settings['connectionRetrySeconds'] as int? ?? 5, commandTimeoutSeconds: settings['commandTimeoutSeconds'] as int? ?? 10, ); } /// Get servers by type List getServersByType(ServerType type) { return servers.where((s) => s.type == type).toList(); } /// Get server that owns a camera ID ServerConfig? getServerForCamera(int cameraId) { for (final server in servers) { if (server.ownsCamera(cameraId)) { return server; } } return null; } /// Get server that owns a monitor ID ServerConfig? getServerForMonitor(int monitorId) { for (final server in servers) { if (server.ownsMonitor(monitorId)) { return server; } } return null; } /// Get total camera count across all servers int get totalCameras { int count = 0; for (final server in servers) { count += (server.cameraRangeEnd - server.cameraRangeStart + 1); } return count; } /// Get total monitor count across all servers int get totalMonitors { int count = 0; for (final server in servers) { count += (server.monitorRangeEnd - server.monitorRangeStart + 1); } return count; } /// Get all camera IDs List get allCameraIds { final ids = []; for (final server in servers) { for (int i = server.cameraRangeStart; i <= server.cameraRangeEnd; i++) { ids.add(i); } } ids.sort(); return ids; } /// Get all monitor IDs List get allMonitorIds { final ids = []; for (final server in servers) { for (int i = server.monitorRangeStart; i <= server.monitorRangeEnd; i++) { ids.add(i); } } ids.sort(); return ids; } }