"""Converters for core hardware configuration models."""

from radiens_core._converters._common_enums import (
    backbone_mode_from_proto,
    port_to_proto,
)
from radiens_core._generated import allegoserver_pb2
from radiens_core.models.core_config import CableDelay, CoreConfig, SetCoreConfigRequest
from radiens_core.models.ports import Port


def core_config_from_proto(proto: allegoserver_pb2.ConfigCore) -> CoreConfig:
    """Convert ConfigCore proto to domain model."""
    cable_delays = {}
    for key, val in proto.cableDelays.cableDelays.items():
        cable_delays[key] = CableDelay(
            port=Port(val.port),
            cable_delay=val.cableDelay,
            is_auto=val.isAuto,
        )

    return CoreConfig(
        allego_core_server_port=proto.allegoCoreServerPort,
        base_samp_freq=proto.baseSampFreq,
        stream_loop_dur_ms=proto.streamLoopDurMs,
        backbone_mode=backbone_mode_from_proto(proto.backboneMode),
        has_xdaq_gpio_expander=proto.hasXDAQGPIOExpander,
        cable_delays=cable_delays,
    )


def set_core_config_to_proto(
    req: SetCoreConfigRequest,
) -> allegoserver_pb2.SetConfigCoreRequest:
    """Convert SetCoreConfigRequest domain model to proto."""
    return build_update_core_config_proto(
        samp_freq=req.samp_freq,
        loop_dur=req.loop_dur,
        pcache_persistence=req.pcache_persistence,
        cable_delay=req.cable_delay,
    )


def build_update_core_config_proto(
    *,
    samp_freq: float | None = None,
    loop_dur: float | None = None,
    pcache_persistence: float | None = None,
    cable_delay: CableDelay | None = None,
) -> allegoserver_pb2.SetConfigCoreRequest:
    """Build a SetConfigCoreRequest proto from individual parameters."""
    proto = allegoserver_pb2.SetConfigCoreRequest()

    if samp_freq is not None:
        proto.sampFreq = samp_freq
    if loop_dur is not None:
        proto.loopDur = loop_dur
    if pcache_persistence is not None:
        proto.pcachePersistence = pcache_persistence
    if cable_delay is not None:
        proto.cableDelay.port = port_to_proto(cable_delay.port)
        proto.cableDelay.cableDelay = cable_delay.cable_delay
        proto.cableDelay.isAuto = cable_delay.is_auto

    return proto
