SXXXXXXX_FlightMonitor/flightmonitor/data/area_profile_manager.py
2025-06-10 13:43:58 +02:00

114 lines
4.6 KiB
Python

# FlightMonitor/data/area_profile_manager.py
"""
Manages loading, saving, and handling of geographic area profiles.
"""
import json
import os
from typing import Dict, Optional, List
from ..utils.logger import get_logger
from . import config as app_config
module_logger = get_logger(__name__)
PROFILE_FILENAME = "area_profiles.json"
DEFAULT_PROFILE_NAME = "Default Zone"
class AreaProfileManager:
"""
Handles reading from and writing to the area profiles JSON file.
"""
def __init__(self, profiles_directory: str = "config"):
"""
Initializes the AreaProfileManager.
Args:
profiles_directory: The directory where the profiles file will be stored.
"""
self.profiles_path = os.path.join(os.path.abspath(profiles_directory), PROFILE_FILENAME)
self._profiles: Dict[str, Dict[str, float]] = {}
self._load_profiles()
def _create_default_profile(self) -> Dict[str, float]:
"""Creates the default profile from the application config."""
return {
"lat_min": app_config.DEFAULT_BBOX_LAT_MIN,
"lon_min": app_config.DEFAULT_BBOX_LON_MIN,
"lat_max": app_config.DEFAULT_BBOX_LAT_MAX,
"lon_max": app_config.DEFAULT_BBOX_LON_MAX,
}
def _load_profiles(self):
"""Loads profiles from the JSON file and ensures the default profile exists."""
# Start with the mandatory default profile
self._profiles = {DEFAULT_PROFILE_NAME: self._create_default_profile()}
if os.path.exists(self.profiles_path):
try:
with open(self.profiles_path, "r") as f:
user_profiles = json.load(f)
if isinstance(user_profiles, dict):
# Merge user profiles, default profile cannot be overwritten
for name, data in user_profiles.items():
if name != DEFAULT_PROFILE_NAME:
self._profiles[name] = data
module_logger.info(f"Loaded {len(user_profiles)} user profiles from {self.profiles_path}")
except (json.JSONDecodeError, IOError) as e:
module_logger.error(f"Error loading profiles from {self.profiles_path}: {e}")
else:
module_logger.info("Area profiles file not found. Starting with default profile.")
# We can optionally save the default profile to create the file on first run
self._save_profiles()
def _save_profiles(self):
"""Saves the current user-defined profiles to the JSON file."""
# Ensure the directory exists
try:
os.makedirs(os.path.dirname(self.profiles_path), exist_ok=True)
except OSError as e:
module_logger.error(f"Could not create directory for profiles file: {e}")
return
# Prepare user-defined profiles for saving (exclude the default)
profiles_to_save = {
name: data for name, data in self._profiles.items() if name != DEFAULT_PROFILE_NAME
}
try:
with open(self.profiles_path, "w") as f:
json.dump(profiles_to_save, f, indent=4)
module_logger.info(f"Successfully saved {len(profiles_to_save)} profiles to {self.profiles_path}")
except IOError as e:
module_logger.error(f"Error saving profiles to {self.profiles_path}: {e}")
def get_profile_names(self) -> List[str]:
"""Returns a sorted list of all available profile names."""
return sorted(self._profiles.keys())
def get_profile_data(self, name: str) -> Optional[Dict[str, float]]:
"""Returns the BBox data for a given profile name."""
return self._profiles.get(name)
def save_profile(self, name: str, data: Dict[str, float]) -> bool:
"""
Saves a new or updated profile. Returns False if name is invalid or default.
"""
if not name or name == DEFAULT_PROFILE_NAME:
module_logger.warning(f"Attempt to save invalid or default profile name: '{name}'")
return False
self._profiles[name] = data
self._save_profiles()
return True
def delete_profile(self, name: str) -> bool:
"""Deletes a profile. Returns False if the profile is default or not found."""
if name == DEFAULT_PROFILE_NAME:
module_logger.warning("Cannot delete the default profile.")
return False
if name in self._profiles:
del self._profiles[name]
self._save_profiles()
return True
module_logger.warning(f"Profile '{name}' not found for deletion.")
return False