// Copyright 2019 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.

//! Online Insertion and Removal worker.

use {
    anyhow::{format_err, Context as _},
    fidl::endpoints::Proxy,
    fidl_fuchsia_hardware_ethernet_ext::is_physical,
    futures::stream::{Stream, StreamExt as _, TryStreamExt as _},
    io_util::{open_directory_in_namespace, OPEN_RIGHT_READABLE},
    network_manager_core::oir::OIRInfo,
    std::fs,
    std::os::unix::io::AsRawFd,
    std::path,
};

/// A node that represents the directory it is in.
///
/// `/dir` and `/dir/.` point to the same directory.
const THIS_DIRECTORY: &str = ".";

fn ethdir_path() -> std::path::PathBuf {
    let options: crate::Opt = argh::from_env();
    path::Path::new(&options.dev_path).join("class/ethernet")
}

async fn device_found(filename: &std::path::PathBuf) -> Result<Option<OIRInfo>, anyhow::Error> {
    let file_path = ethdir_path().join(filename);
    let device = fs::File::open(&file_path)
        .with_context(|| format!("could not open {}", file_path.display()))?;
    let topological_path = fdio::device_get_topo_path(&device)
        .with_context(|| format!("fdio::device_get_topo_path({})", file_path.display()))?;
    let device_fd = device.as_raw_fd();
    let mut client = 0;
    // Safe because we're passing a valid fd.
    fuchsia_zircon::Status::ok(unsafe {
        fdio::fdio_sys::fdio_get_service_handle(device_fd, &mut client)
    })
    .with_context(|| {
        format!("fuchsia_zircon::sys::fdio_get_service_handle({})", file_path.display())
    })?;
    // Safe because we checked the return status above.
    let client = fuchsia_zircon::Channel::from(unsafe { fuchsia_zircon::Handle::from_raw(client) });

    let ethernet_device =
        fidl::endpoints::ClientEnd::<fidl_fuchsia_hardware_ethernet::DeviceMarker>::new(client)
            .into_proxy()?;

    if let Ok(device_info) = ethernet_device.get_info().await {
        let device_info: fidl_fuchsia_hardware_ethernet_ext::EthernetInfo = device_info.into();
        let device_channel = ethernet_device
            .into_channel()
            .map_err(|fidl_fuchsia_hardware_ethernet::DeviceProxy { .. }| {
                anyhow::anyhow!("failed to convert device proxy into channel")
            })?
            .into_zx_channel();

        info!("Device found: topo_path {} info {:?}", topological_path, device_info);
        if is_physical(device_info.features) {
            return Ok(Some(OIRInfo {
                action: network_manager_core::oir::Action::ADD,
                file_path: file_path.to_str().unwrap().to_string(),
                topological_path,
                device_information: Some(device_info),
                device_channel: Some(device_channel),
            }));
        } else {
            info!("device not physical {:?}", device_info);
        }
    }

    Ok(None)
}

fn device_removed(topological_path: &std::path::PathBuf) -> OIRInfo {
    info!("removing device topo path {:?}", topological_path);
    OIRInfo {
        action: network_manager_core::oir::Action::REMOVE,
        topological_path: topological_path.to_str().unwrap().to_string(),
        file_path: "".to_string(),
        device_information: None,
        device_channel: None,
    }
}

/// Returns a `Stream` that yields `OIRInfo`s in response to events from the
/// device filesystem.
pub(super) async fn new_stream(
) -> Result<impl Stream<Item = Result<OIRInfo, anyhow::Error>>, anyhow::Error> {
    let path = ethdir_path();
    let path_as_str = path.to_str().ok_or_else(|| {
        format_err!(
            "path requested for watch is non-utf8 and our non-blocking directory apis require utf8 paths: {:?}.",
            path
        )
    })?;
    debug!("device path: {}", path_as_str);
    let dir_proxy = open_directory_in_namespace(path_as_str, OPEN_RIGHT_READABLE)?;
    let watcher = fuchsia_vfs_watcher::Watcher::new(dir_proxy)
        .await
        .with_context(|| format!("could not watch {:?}", path))?;

    Ok(watcher
        .map(|r| r.context("getting next VFS event from"))
        .try_filter_map(|fuchsia_vfs_watcher::WatchMessage { event, filename }| async move {
            info!("received {:?} event for filename: {:?}", event, filename);

            if filename == path::PathBuf::from(THIS_DIRECTORY) {
                debug!("skipping filename = {}", filename.display());
                return Ok(None);
            }

            match event {
                fuchsia_vfs_watcher::WatchEvent::ADD_FILE
                | fuchsia_vfs_watcher::WatchEvent::EXISTING => Ok(device_found(&filename).await?),
                fuchsia_vfs_watcher::WatchEvent::IDLE => Ok(None),
                fuchsia_vfs_watcher::WatchEvent::REMOVE_FILE => Ok(Some(device_removed(&filename))),
                event => {
                    warn!("received unknown event {:?} for filename: {:?}", event, filename);
                    Ok(None)
                }
            }
        })
        .map(move |r| r.with_context(|| format!("watching {:?}", path))))
}
