// 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.
use {
    anyhow::{Context as _, Result},
    fidl_fuchsia_buildinfo as buildinfo, fidl_fuchsia_developer_remotecontrol as rcs,
    fidl_fuchsia_device as fdevice, fidl_fuchsia_hwinfo as hwinfo,
    fidl_fuchsia_net_interfaces as fnet_interfaces,
    fidl_fuchsia_net_interfaces_ext as fnet_interfaces_ext, fidl_fuchsia_sysinfo as sysinfo,
    fuchsia_zircon as zx,
    std::collections::HashMap,
    tracing::*,
};

pub struct HostIdentifier {
    pub(crate) interface_state_proxy: fnet_interfaces::StateProxy,
    pub(crate) name_provider_proxy: fdevice::NameProviderProxy,
    pub(crate) device_info_proxy: hwinfo::DeviceProxy,
    pub(crate) system_info_proxy: sysinfo::SysInfoProxy,
    pub(crate) build_info_proxy: buildinfo::ProviderProxy,
    pub(crate) boot_timestamp_nanos: u64,
}

fn connect_to_protocol<P: fidl::endpoints::DiscoverableProtocolMarker>() -> Result<P::Proxy> {
    fuchsia_component::client::connect_to_protocol::<P>().context(P::DEBUG_NAME)
}

impl HostIdentifier {
    pub fn new() -> Result<Self> {
        let interface_state_proxy = connect_to_protocol::<fnet_interfaces::StateMarker>()?;
        let name_provider_proxy = connect_to_protocol::<fdevice::NameProviderMarker>()?;
        let device_info_proxy = connect_to_protocol::<hwinfo::DeviceMarker>()?;
        let system_info_proxy = connect_to_protocol::<sysinfo::SysInfoMarker>()?;
        let build_info_proxy = connect_to_protocol::<buildinfo::ProviderMarker>()?;
        let boot_timestamp_nanos = (fuchsia_runtime::utc_time().into_nanos()
            - zx::Time::get_monotonic().into_nanos()) as u64;
        return Ok(Self {
            interface_state_proxy,
            name_provider_proxy,
            device_info_proxy,
            system_info_proxy,
            build_info_proxy,
            boot_timestamp_nanos,
        });
    }

    pub async fn identify(&self) -> Result<rcs::IdentifyHostResponse, rcs::IdentifyHostError> {
        let stream = fnet_interfaces_ext::event_stream_from_state(
            &self.interface_state_proxy,
            fnet_interfaces_ext::IncludedAddresses::OnlyAssigned,
        )
        .map_err(|e| {
            error!(%e, "Getting interface watcher failed");
            rcs::IdentifyHostError::ListInterfacesFailed
        })?;
        let ilist = fnet_interfaces_ext::existing(
            stream,
            HashMap::<u64, fnet_interfaces_ext::PropertiesAndState<()>>::new(),
        )
        .await
        .map_err(|e| {
            error!(%e, "Getting existing interfaces failed");
            rcs::IdentifyHostError::ListInterfacesFailed
        })?;

        let serial_number = 'serial: {
            match self.system_info_proxy.get_serial_number().await {
                Ok(Ok(serial)) => break 'serial Some(serial),
                Ok(Err(status)) => {
                    let status = zx::Status::from_raw(status);
                    warn!(%status, "Failed to get serial from SysInfo")
                }
                Err(err) => error!(%err, "SysInfoProxy internal err"),
            }

            match self.device_info_proxy.get_info().await {
                Ok(info) => break 'serial info.serial_number,
                Err(err) => error!(%err, "DeviceProxy internal err"),
            }

            None
        };

        let (product_config, board_config) = self
            .build_info_proxy
            .get_build_info()
            .await
            .map_err(|e| error!(%e, "buildinfo::ProviderProxy internal err"))
            .ok()
            .and_then(|i| Some((i.product_config, i.board_config)))
            .unwrap_or((None, None));

        let addresses = ilist
            .into_iter()
            .map(|(_, v): (u64, _)| v)
            .flat_map(|properties_and_state| {
                properties_and_state.properties.addresses.into_iter().filter_map(
                    |fnet_interfaces_ext::Address { addr, valid_until: _, assignment_state }| {
                        match assignment_state {
                            fnet_interfaces::AddressAssignmentState::Assigned => Some(addr),
                            fnet_interfaces::AddressAssignmentState::Tentative
                            | fnet_interfaces::AddressAssignmentState::Unavailable => None,
                        }
                    },
                )
            })
            .collect::<Vec<_>>();

        let addresses = Some(addresses);

        let nodename = match self.name_provider_proxy.get_device_name().await {
            Ok(result) => match result {
                Ok(name) => Some(name),
                Err(err) => {
                    error!(%err, "NameProvider internal error");
                    return Err(rcs::IdentifyHostError::GetDeviceNameFailed);
                }
            },
            Err(err) => {
                error!(%err, "Getting nodename failed");
                return Err(rcs::IdentifyHostError::GetDeviceNameFailed);
            }
        };

        let boot_timestamp_nanos = Some(self.boot_timestamp_nanos);

        Ok(rcs::IdentifyHostResponse {
            nodename,
            addresses,
            serial_number,
            boot_timestamp_nanos,
            product_config,
            board_config,
            ..Default::default()
        })
    }
}
