// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Rather than reuse existing _ext types, we define intermediary types for
//! JSON serialization to avoid coupling too closely to particular FIDL
//! protocols.

use fidl_fuchsia_net_routes_ext as froutes_ext;
use net_types::{ip::IpAddress as _, Witness as _};
use thiserror::Error;

#[derive(serde::Serialize, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Subnet<T> {
    pub(crate) addr: T,
    pub(crate) prefix_len: u8,
}

impl From<fidl_fuchsia_net_ext::Subnet> for Subnet<std::net::IpAddr> {
    fn from(ext: fidl_fuchsia_net_ext::Subnet) -> Subnet<std::net::IpAddr> {
        let fidl_fuchsia_net_ext::Subnet {
            addr: fidl_fuchsia_net_ext::IpAddress(addr),
            prefix_len,
        } = ext;
        Subnet { addr, prefix_len }
    }
}

impl<A: net_types::ip::IpAddress> From<net_types::ip::Subnet<A>> for Subnet<std::net::IpAddr> {
    fn from(sub: net_types::ip::Subnet<A>) -> Subnet<std::net::IpAddr> {
        let addr = sub.network().to_ip_addr().into();
        let prefix_len = sub.prefix();
        Subnet { addr, prefix_len }
    }
}

#[derive(serde::Serialize, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) enum AddressAssignmentState {
    Tentative,
    Assigned,
    Unavailable,
}

impl From<fidl_fuchsia_net_interfaces::AddressAssignmentState> for AddressAssignmentState {
    fn from(value: fidl_fuchsia_net_interfaces::AddressAssignmentState) -> Self {
        match value {
            fidl_fuchsia_net_interfaces::AddressAssignmentState::Tentative => Self::Tentative,
            fidl_fuchsia_net_interfaces::AddressAssignmentState::Assigned => Self::Assigned,
            fidl_fuchsia_net_interfaces::AddressAssignmentState::Unavailable => Self::Unavailable,
        }
    }
}

#[derive(serde::Serialize, Ord, PartialOrd, Eq, PartialEq)]
pub(crate) struct Address<I> {
    #[serde(flatten)]
    pub(crate) subnet: Subnet<I>,
    pub(crate) valid_until: Option<i64>,
    pub(crate) assignment_state: AddressAssignmentState,
}

impl<I> Address<I> {
    fn map<I2, F: Fn(I) -> I2>(self, f: F) -> Address<I2> {
        let Self { subnet: Subnet { addr, prefix_len }, valid_until, assignment_state } = self;
        Address { subnet: Subnet { addr: f(addr), prefix_len }, valid_until, assignment_state }
    }
}

#[derive(serde::Serialize)]
pub(crate) struct Addresses {
    pub(crate) ipv4: Vec<Address<std::net::Ipv4Addr>>,
    pub(crate) ipv6: Vec<Address<std::net::Ipv6Addr>>,
}

impl Addresses {
    pub(crate) fn all_addresses(self) -> impl Iterator<Item = Address<std::net::IpAddr>> {
        let Self { ipv4, ipv6 } = self;
        ipv4.into_iter()
            .map(|a| a.map(Into::into))
            .chain(ipv6.into_iter().map(|a| a.map(Into::into)))
    }
}

impl<I: Iterator<Item = fidl_fuchsia_net_interfaces_ext::Address>> From<I> for Addresses {
    fn from(addresses: I) -> Addresses {
        use itertools::Itertools as _;

        let (mut ipv4, mut ipv6): (Vec<_>, Vec<_>) = addresses.into_iter().partition_map(
            |fidl_fuchsia_net_interfaces_ext::Address { addr, valid_until, assignment_state }| {
                let fidl_fuchsia_net_ext::Subnet {
                    addr: fidl_fuchsia_net_ext::IpAddress(addr),
                    prefix_len,
                } = addr.into();
                let assignment_state = assignment_state.into();

                fn new_address<I>(
                    addr: I,
                    prefix_len: u8,
                    valid_until: i64,
                    assignment_state: AddressAssignmentState,
                ) -> Address<I> {
                    let valid_until = (valid_until != i64::MAX).then_some(valid_until);
                    Address { subnet: Subnet { addr, prefix_len }, valid_until, assignment_state }
                }
                match addr {
                    std::net::IpAddr::V4(addr) => itertools::Either::Left(new_address(
                        addr,
                        prefix_len,
                        valid_until,
                        assignment_state,
                    )),
                    std::net::IpAddr::V6(addr) => itertools::Either::Right(new_address(
                        addr,
                        prefix_len,
                        valid_until,
                        assignment_state,
                    )),
                }
            },
        );
        ipv4.sort();
        ipv6.sort();
        Addresses { ipv4, ipv6 }
    }
}

#[derive(serde::Serialize)]
pub(crate) enum DeviceClass {
    Loopback,
    Virtual,
    Ethernet,
    Wlan,
    Ppp,
    Bridge,
    WlanAp,
}

impl From<fidl_fuchsia_net_interfaces::DeviceClass> for DeviceClass {
    fn from(device_class: fidl_fuchsia_net_interfaces::DeviceClass) -> Self {
        match device_class {
            fidl_fuchsia_net_interfaces::DeviceClass::Loopback(
                fidl_fuchsia_net_interfaces::Empty,
            ) => Self::Loopback,
            fidl_fuchsia_net_interfaces::DeviceClass::Device(device_class) => match device_class {
                fidl_fuchsia_hardware_network::DeviceClass::Virtual => Self::Virtual,
                fidl_fuchsia_hardware_network::DeviceClass::Ethernet => Self::Ethernet,
                fidl_fuchsia_hardware_network::DeviceClass::Wlan => Self::Wlan,
                fidl_fuchsia_hardware_network::DeviceClass::Ppp => Self::Ppp,
                fidl_fuchsia_hardware_network::DeviceClass::Bridge => Self::Bridge,
                fidl_fuchsia_hardware_network::DeviceClass::WlanAp => Self::WlanAp,
            },
        }
    }
}

#[derive(serde::Serialize)]
/// Intermediary struct for serializing interface properties into JSON.
pub(crate) struct InterfaceView {
    pub(crate) nicid: u64,
    pub(crate) name: String,
    pub(crate) device_class: DeviceClass,
    pub(crate) online: bool,
    pub(crate) addresses: Addresses,
    pub(crate) has_default_ipv4_route: bool,
    pub(crate) has_default_ipv6_route: bool,
    pub(crate) mac: Option<fidl_fuchsia_net_ext::MacAddress>,
}

impl From<(fidl_fuchsia_net_interfaces_ext::Properties, Option<fidl_fuchsia_net::MacAddress>)>
    for InterfaceView
{
    fn from(
        t: (fidl_fuchsia_net_interfaces_ext::Properties, Option<fidl_fuchsia_net::MacAddress>),
    ) -> InterfaceView {
        let (
            fidl_fuchsia_net_interfaces_ext::Properties {
                id,
                name,
                device_class,
                online,
                addresses,
                has_default_ipv4_route,
                has_default_ipv6_route,
            },
            mac,
        ) = t;
        InterfaceView {
            nicid: id.get(),
            name,
            device_class: device_class.into(),
            online,
            addresses: addresses.into_iter().into(),
            has_default_ipv4_route,
            has_default_ipv6_route,
            mac: mac.map(Into::into),
        }
    }
}

#[derive(serde::Serialize, Ord, PartialOrd, Eq, PartialEq)]
/// Intermediary struct for serializing IP forwarding table entries into JSON.
pub struct ForwardingEntry {
    #[serde(rename = "destination")]
    subnet: Subnet<std::net::IpAddr>,
    #[serde(rename = "nicid")]
    device_id: u64,
    #[serde(rename = "gateway")]
    next_hop: Option<std::net::IpAddr>,
    metric: u32,
}

/// Errors returned when converting from [`froutes_ext::InstalledRoute`]
/// to [`ForwardingEntry`].
#[derive(Debug, Error)]
pub enum ForwardingEntryConversionError {
    #[error("the route's action was unknown")]
    UnknownRouteAction,
}

impl<I: net_types::ip::Ip> TryFrom<froutes_ext::InstalledRoute<I>> for ForwardingEntry {
    type Error = ForwardingEntryConversionError;
    fn try_from(route: froutes_ext::InstalledRoute<I>) -> Result<Self, Self::Error> {
        let froutes_ext::InstalledRoute {
            route: froutes_ext::Route { destination, action, properties: _ },
            effective_properties: froutes_ext::EffectiveRouteProperties { metric },
        } = route;
        let (device_id, next_hop) = match action {
            froutes_ext::RouteAction::Forward(froutes_ext::RouteTarget {
                outbound_interface,
                next_hop,
            }) => (outbound_interface, next_hop),
            froutes_ext::RouteAction::Unknown => {
                return Err(ForwardingEntryConversionError::UnknownRouteAction)
            }
        };
        let subnet = destination.into();
        let next_hop = next_hop.map(|next_hop| next_hop.get().to_ip_addr().into());
        Ok(Self { subnet, device_id, next_hop, metric })
    }
}

pub struct NeighborTableEntryIteratorItemVariants<T> {
    existing: T,
    added: T,
    changed: T,
    removed: T,
    idle: T,
}

impl<T> NeighborTableEntryIteratorItemVariants<T> {
    pub fn select(self, item: &fidl_fuchsia_net_neighbor::EntryIteratorItem) -> T {
        use fidl_fuchsia_net_neighbor::EntryIteratorItem;
        let Self { existing, added, changed, removed, idle } = self;
        match item {
            EntryIteratorItem::Existing(_) => existing,
            EntryIteratorItem::Added(_) => added,
            EntryIteratorItem::Changed(_) => changed,
            EntryIteratorItem::Removed(_) => removed,
            EntryIteratorItem::Idle(_) => idle,
        }
    }
}

impl<T> IntoIterator for NeighborTableEntryIteratorItemVariants<T> {
    type Item = T;
    type IntoIter = <[T; 5] as IntoIterator>::IntoIter;

    fn into_iter(self) -> Self::IntoIter {
        let Self { existing, added, changed, removed, idle } = self;
        [existing, added, changed, removed, idle].into_iter()
    }
}

pub const DISPLAYED_NEIGH_ENTRY_VARIANTS: NeighborTableEntryIteratorItemVariants<&'static str> =
    NeighborTableEntryIteratorItemVariants {
        existing: "EXISTING",
        added: "ADDED",
        changed: "CHANGED",
        removed: "REMOVED",
        idle: "IDLE",
    };

/// Intermediary type for serializing Entry (e.g. into JSON).
#[derive(serde::Serialize)]
pub struct NeighborTableEntry {
    interface: u64,
    neighbor: std::net::IpAddr,
    state: &'static str,
    mac: Option<fidl_fuchsia_net_ext::MacAddress>,
}

impl From<fidl_fuchsia_net_neighbor_ext::Entry> for NeighborTableEntry {
    fn from(
        fidl_fuchsia_net_neighbor_ext::Entry {
            interface,
            neighbor,
            state,
            mac,
            // Ignored since the tabular format ignores this field.
            updated_at: _,
        }: fidl_fuchsia_net_neighbor_ext::Entry,
    ) -> NeighborTableEntry {
        let fidl_fuchsia_net_ext::IpAddress(neighbor) = neighbor.into();
        NeighborTableEntry {
            interface,
            neighbor,
            state: fidl_fuchsia_net_neighbor_ext::display_entry_state(&state),
            mac: mac.map(|mac| mac.into()),
        }
    }
}
