"""
Scientific Gallery Configuration Management

This module provides dataclasses and utilities for managing configuration
of the scientific gallery system, including paths, gallery settings,
UI preferences, and data sources.
"""

from dataclasses import dataclass, field, asdict
from pathlib import Path
import yaml


@dataclass
class PathConfig:
    """Configuration for system paths and directories."""
    work_dir: str
    web_folder: str
    cgi_script: str
    config_path: str


@dataclass
class GalleryConfig:
    """Configuration for gallery generation and display settings."""
    plot_root: str
    png_dpi: int
    backup_folder: str


@dataclass
class UIConfig:
    """Configuration for user interface behavior and preferences."""
    max_recent_plots: int
    search_debounce_ms: int


@dataclass
class MetadataConfig:
    """Configuration for metadata handling."""
    cache_enabled: bool = True
    inherit_from_parent: bool = True
    supported_formats: list[str] = field(
        default_factory=lambda: ['.yaml', '.yml', '.json']
    )


@dataclass
class GalleryItem:
    """Represents a single data source for the gallery."""
    name: str
    path: Path


@dataclass
class Config:
    """
    Main configuration class that aggregates all gallery settings.
    
    Provides backward compatibility properties and methods for loading
    configuration from YAML files.
    """
    paths: PathConfig
    gallery: GalleryConfig
    ui: UIConfig
    metadata: MetadataConfig
    sources: list[GalleryItem] = field(default_factory=list)

    @property
    def web_folder(self):
        """Backward compatibility property for web folder path."""
        return self.paths.web_folder

    @property
    def png_dpi(self):
        """Backward compatibility property for PNG conversion DPI."""
        return self.gallery.png_dpi

    @property
    def plot_root(self):
        """Backward compatibility property for plot root directory."""
        return self.gallery.plot_root

    @property
    def backup_folder(self):
        """Backward compatibility property for backup folder path."""
        return self.gallery.backup_folder

    @classmethod
    def from_yaml(cls, yaml_file: str) -> "Config":
        """
        Load configuration from a YAML file.

        Args:
            yaml_file: Path to the YAML configuration file

        Returns:
            Config instance with loaded settings

        Raises:
            FileNotFoundError: If the YAML file doesn't exist
            yaml.YAMLError: If the YAML file is malformed
        """
        with open(yaml_file, "r") as f:
            data = yaml.safe_load(f)

        paths_data = data.get('paths', {})
        gallery_data = data.get('gallery', {})
        ui_data = data.get('ui', {})
        metadata_data = data.get('metadata', {})
        sources_data = data.get('sources', [])

        paths = PathConfig(**paths_data)
        gallery = GalleryConfig(**gallery_data)
        ui = UIConfig(**ui_data)
        metadata = MetadataConfig(**metadata_data)

        sources = [
            GalleryItem(name=source["name"], path=Path(source["path"]))
            for source in sources_data
        ]

        return cls(
            paths=paths,
            gallery=gallery,
            ui=ui,
            metadata=metadata,
            sources=sources
        )

    def to_yaml(self, yaml_file: str) -> None:
        """
        Save the current configuration to a YAML file.

        Args:
            yaml_file: Path where to save the YAML configuration

        Raises:
            IOError: If unable to write to the specified file
        """
        with open(yaml_file, "w") as f:
            yaml.dump(asdict(self), f, default_flow_style=False)


if __name__ == "__main__":
    config = Config.from_yaml("config.yaml")
    print("Loaded config successfully:", config)
