"""SOFIA v1 configuration.

Lightweight 4-stage StripNet+DCNv4 backbone variants (`tiny_tiny`/`tiny`/`small`
/`small_v2`) plus simple GGeM-based heads with optional altitude-FiLM and
text-FiLM modulation.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal


@dataclass
class SOFIAv1Config:
    # -------- Backbone --------
    variant: Literal["tiny_tiny", "tiny", "small", "small_v2"] = "small"
    in_channels: int = 3
    input_size: int = 256
    # DCN op variant. "v2" (default) uses torchvision DeformConv2d — stable.
    # "v4" uses OpenGVLab DCNv4 — faster but has known C++-extension memory
    # leak (~9 MB per forward) that OOMs in long training runs.
    dcn_variant: Literal["v2", "v4"] = "v2"

    # -------- Heads --------
    d_descriptor: int = 1024
    return_normalized: bool = False     # False → wrapper handles L2 after gated fusion

    # Altitude-FiLM (UAV head only).
    use_film_altitude: bool = True
    altitude_norm: float = 500.0

    # Text-FiLM (mid-level fusion). Both can be toggled independently.
    use_text_film_uav: bool = True
    use_text_film_sat: bool = True
    text_film_dim: int = 1024
    text_film_hidden: int = 256

    def summary(self) -> str:
        return (
            f"SOFIAv1Config(variant={self.variant}, d={self.d_descriptor}, "
            f"film_alt={self.use_film_altitude}, "
            f"text_film(sat={self.use_text_film_sat},uav={self.use_text_film_uav}))"
        )
