//! `plexus-iface` — interface adapters.
//!
//! Each adapter owns its I/O and speaks `mpsc<TxFrame>` / `mpsc<RxFrame>` to the
//! gateway (`ARCHITECTURE.md` §4). `tokio`-based. The gateway itself is
//! runtime-agnostic; this crate is where the runtime lives.
//!
//! v0 status: the [`Interface`] trait and frame types are defined; the concrete
//! adapters are stub modules pending Phase 2 (§11.2).
#![allow(
    dead_code,
    unused_variables,
    clippy::missing_errors_doc,
    clippy::module_name_repetitions,
    clippy::must_use_candidate
)]

pub mod error;
pub mod hdlc;
pub mod local;
pub mod tcp;
pub mod udp;

use async_trait::async_trait;
use bytes::Bytes;
use tokio::sync::mpsc;
use tokio_util::sync::CancellationToken;

use plexus_gateway::InterfaceId;

pub use error::Error;
pub use tcp::{TcpClient, TcpServer};

/// The kind of an interface adapter (`ARCHITECTURE.md` §4.2).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum InterfaceKind {
    /// TCP client or server.
    Tcp,
    /// UDP.
    Udp,
    /// Same-host shared-instance control socket.
    Local,
    /// RNode LoRa radio over serial.
    RNode,
    /// Generic serial.
    Serial,
    /// KISS TNC.
    Kiss,
    /// AX.25 over KISS.
    Ax25Kiss,
    /// Auto-discovery (UDP multicast).
    Auto,
    /// I2P transit.
    I2p,
    /// High-throughput inter-transport-node backbone.
    Backbone,
}

/// Send priority for an outbound frame.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Priority {
    /// Bulk / best-effort.
    Low,
    /// Default.
    Normal,
    /// Latency-sensitive (e.g. link keepalives).
    High,
}

/// A frame to transmit (gateway → interface).
#[derive(Debug, Clone)]
pub struct TxFrame {
    /// Bytes to send.
    pub bytes: Bytes,
    /// Send priority.
    pub priority: Priority,
}

/// A received frame (interface → gateway), with optional radio metadata.
#[derive(Debug, Clone)]
pub struct RxFrame {
    /// Bytes received.
    pub bytes: Bytes,
    /// Received signal strength, if the medium reports it.
    pub rssi: Option<i16>,
    /// Signal-to-noise ratio, if the medium reports it.
    pub snr: Option<f32>,
}

/// Channels and lifecycle handle returned by a started interface (§4.1).
pub struct InterfaceHandle {
    /// The interface's id.
    pub id: InterfaceId,
    /// Gateway → interface frames.
    pub tx: mpsc::Sender<TxFrame>,
    /// Interface → gateway frames.
    pub rx: mpsc::Receiver<RxFrame>,
    /// Cancellation token to stop the interface's I/O tasks.
    pub cancel: CancellationToken,
}

/// A network interface adapter (`ARCHITECTURE.md` §4.1).
#[async_trait]
pub trait Interface: Send + 'static {
    /// This interface's stable id.
    fn id(&self) -> InterfaceId;
    /// This interface's kind.
    fn kind(&self) -> InterfaceKind;
    /// This interface's MTU in bytes.
    fn mtu(&self) -> usize;

    /// Spawn the interface's I/O task(s), returning the channel pair and a
    /// cancellation token.
    async fn start(self: Box<Self>) -> Result<InterfaceHandle, Error>;
}
