// Copyright 2022 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 fidl::endpoints::{DiscoverableProtocolMarker, Proxy};
use fidl_fuchsia_dash::LauncherError;
use fuchsia_component::client::connect_channel_to_protocol;
use fuchsia_component::server::ServiceFs;
use futures::StreamExt;
use tracing::warn;
use vfs::directory::entry_container::Directory;
use vfs::directory::helper::DirectlyMutable;
use vfs::execution_scope::ExecutionScope;
use vfs::path::Path;
use vfs::service::endpoint;
use {
    fidl_fuchsia_component_runner as fcrunner, fidl_fuchsia_io as fio,
    fidl_fuchsia_process as fproc, fuchsia_async as fasync,
};

pub fn package_layout(
    svc_dir: fio::DirectoryProxy,
    target_dir: fio::DirectoryProxy,
) -> Vec<fproc::NameInfo> {
    vec![to_name_info("/svc", svc_dir), to_name_info("/pkg", target_dir)]
}

/// Returns directory handles + paths for a nested layout using the given directories.
/// In this layout, all instance directories are nested as subdirectories of the root.
/// e.g - namespace is under `/ns`, outgoing directory is under `/out`, etc.
pub fn nest_all_instance_dirs(
    ns_entries: Vec<fcrunner::ComponentNamespaceEntry>,
    exposed_dir: fio::DirectoryProxy,
    svc_dir: fio::DirectoryProxy,
    out_dir: Option<fio::DirectoryProxy>,
    runtime_dir: Option<fio::DirectoryProxy>,
) -> Vec<fproc::NameInfo> {
    let mut name_infos = vec![];

    name_infos.push(to_name_info("/exposed", exposed_dir));
    name_infos.push(to_name_info("/svc", svc_dir));

    for entry in ns_entries {
        let path = format!("/ns{}", entry.path.unwrap());
        let directory = entry.directory.unwrap();
        name_infos.push(fproc::NameInfo { path, directory });
    }

    if let Some(dir) = out_dir {
        name_infos.push(to_name_info("/out", dir));
    }

    if let Some(dir) = runtime_dir {
        name_infos.push(to_name_info("/runtime", dir));
    }

    name_infos
}

pub fn add_tools_to_name_infos(
    tools: Option<fio::DirectoryProxy>,
    name_infos: &mut Vec<fproc::NameInfo>,
) {
    if let Some(dir) = tools {
        name_infos.push(to_name_info("/.dash/tools", dir));
    }
}

/// Returns directory handles + paths for a namespace layout using the given directories.
/// In this layout, the instance namespace is the root. This is a layout that works
/// well for tools and closely resembles what the component instance would see if it queried its
/// own namespace.
///
/// To make the shell work correctly, we need to inject the following into the layout:
/// * fuchsia.process.Resolver and fuchsia.process.Launcher into `/svc`
/// * tools packages, if given, into `/.dash/tools`
///
/// Also returns the corresponding PATH envvar that must be set for the dash shell.
pub async fn instance_namespace_is_root(
    ns_entries: Vec<fcrunner::ComponentNamespaceEntry>,
) -> Vec<fproc::NameInfo> {
    let mut name_infos = vec![];

    for entry in ns_entries {
        let path = entry.path.unwrap();
        let directory = entry.directory.unwrap();

        if path == "/svc" {
            let svc_dir = directory.into_proxy().unwrap();
            let svc_dir = inject_process_launcher_and_resolver(svc_dir).await;
            name_infos.push(to_name_info(&path, svc_dir));
        } else {
            name_infos.push(fproc::NameInfo { path, directory });
        }
    }

    name_infos
}

/// Serves a VFS that contains `fuchsia.process.Launcher` and `fuchsia.process.Resolver`. This is
/// used by the Nested filesystem layout.
pub fn serve_process_launcher_and_resolver_svc_dir() -> Result<fio::DirectoryProxy, LauncherError> {
    // Serve a directory that only provides fuchsia.process.Launcher to dash.
    let (svc_dir, server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>()
        .map_err(|_| LauncherError::Internal)?;

    let mut fs = ServiceFs::new();
    fs.add_proxy_service::<fproc::LauncherMarker, ()>();
    fs.add_proxy_service::<fproc::ResolverMarker, ()>();
    fs.serve_connection(server_end).map_err(|_| LauncherError::ProcessResolver)?;

    fasync::Task::spawn(async move {
        fs.collect::<()>().await;
    })
    .detach();

    Ok(svc_dir)
}

/// Gets the list of all protocols available in the given svc directory and serves a new VFS
/// that injects `fuchsia.process.Launcher` from the launcher namespace and forwards the calls
/// for the other protocols. Also adds the `fuchsia.process.Resolver` for tool trampolines.
async fn inject_process_launcher_and_resolver(svc_dir: fio::DirectoryProxy) -> fio::DirectoryProxy {
    let vfs = vfs::directory::immutable::simple();
    let entries = fuchsia_fs::directory::readdir(&svc_dir).await.unwrap();

    // Create forwarding entries for namespace protocols
    for entry in entries {
        let svc_dir = std::clone::Clone::clone(&svc_dir);
        let protocol_name = entry.name.clone();
        vfs.add_entry(
            protocol_name.clone(),
            endpoint(move |_, channel| {
                let server_end = channel.into_zx_channel().into();
                svc_dir
                    .open(
                        fio::OpenFlags::NOT_DIRECTORY,
                        fio::ModeType::empty(),
                        &protocol_name,
                        server_end,
                    )
                    .unwrap();
            }),
        )
        .unwrap();
    }

    // Add process launcher.
    if let Err(err) = vfs.add_entry(
        fproc::LauncherMarker::PROTOCOL_NAME,
        endpoint(|_, channel| {
            connect_channel_to_protocol::<fproc::LauncherMarker>(channel.into_zx_channel())
                .unwrap();
        }),
    ) {
        warn!(?err, "Could not inject fuchsia.process.Launcher into filesystem layout. Ignoring.");
    }

    // Add process resolver.
    if let Err(err) = vfs.add_entry(
        fproc::ResolverMarker::PROTOCOL_NAME,
        endpoint(|_, channel| {
            connect_channel_to_protocol::<fproc::ResolverMarker>(channel.into_zx_channel())
                .unwrap();
        }),
    ) {
        warn!(?err, "Could not inject fuchsia.process.Resolver into filesystem layout. Ignoring.");
    }
    let (svc_dir, server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>().unwrap();
    let server_end = server_end.into_channel().into();
    vfs.open(
        ExecutionScope::new(),
        fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::RIGHT_WRITABLE,
        Path::dot(),
        server_end,
    );

    svc_dir
}

fn to_name_info(path: &str, directory: fio::DirectoryProxy) -> fproc::NameInfo {
    let directory = directory.into_channel().unwrap().into_zx_channel().into();
    fproc::NameInfo { path: path.to_string(), directory }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::path::PathBuf;
    use tempfile::TempDir;

    fn create_temp_dir(file_name: &str) -> fio::DirectoryProxy {
        // Create a temp directory and put a file with name `file_name` inside it.
        let temp_dir = TempDir::new().unwrap();
        let temp_dir_path = temp_dir.into_path();
        let file_path = temp_dir_path.join(file_name);
        std::fs::write(&file_path, "Hippos Rule!").unwrap();
        let temp_dir_path = temp_dir_path.display().to_string();
        fuchsia_fs::directory::open_in_namespace(&temp_dir_path, fio::OpenFlags::RIGHT_READABLE)
            .unwrap()
    }

    fn create_ns_entries() -> Vec<fcrunner::ComponentNamespaceEntry> {
        let ns_subdir = create_temp_dir("ns_subdir");
        let ns_subdir = ns_subdir.into_channel().unwrap().into_zx_channel().into();
        vec![fcrunner::ComponentNamespaceEntry {
            path: Some("/ns_subdir".to_string()),
            directory: Some(ns_subdir),
            ..Default::default()
        }]
    }

    #[fuchsia::test]
    async fn nest_all_instance_dirs_started_with_tools() {
        let exposed_dir = create_temp_dir("exposed");
        let out_dir = create_temp_dir("out");
        let svc_dir = create_temp_dir("svc");
        let runtime_dir = create_temp_dir("runtime");
        let ns_entries = create_ns_entries();

        let ns = nest_all_instance_dirs(
            ns_entries,
            exposed_dir,
            svc_dir,
            Some(out_dir),
            Some(runtime_dir),
        );
        assert_eq!(ns.len(), 5);

        let mut paths: Vec<String> = ns.iter().map(|n| n.path.clone()).collect();
        paths.sort();
        assert_eq!(paths, vec!["/exposed", "/ns/ns_subdir", "/out", "/runtime", "/svc"]);

        // Make sure that the correct directories were mapped to the correct paths.
        for entry in ns {
            let dir = entry.directory.into_proxy().unwrap();
            let entries = fuchsia_fs::directory::readdir(&dir).await.unwrap();

            // These directories must contain a file with the same name
            let path = PathBuf::from(entry.path);
            let expected_file_name = path.file_name().unwrap().to_str().unwrap().to_string();
            assert_eq!(
                entries,
                vec![fuchsia_fs::directory::DirEntry {
                    name: expected_file_name,
                    kind: fuchsia_fs::directory::DirentKind::File
                }]
            );
        }
    }

    #[fuchsia::test]
    async fn nest_all_instance_dirs_started() {
        let exposed_dir = create_temp_dir("exposed");
        let out_dir = create_temp_dir("out");
        let svc_dir = create_temp_dir("svc");
        let runtime_dir = create_temp_dir("runtime");
        let ns_entries = create_ns_entries();

        let ns = nest_all_instance_dirs(
            ns_entries,
            exposed_dir,
            svc_dir,
            Some(out_dir),
            Some(runtime_dir),
        );
        assert_eq!(ns.len(), 5);

        let mut paths: Vec<String> = ns.iter().map(|n| n.path.clone()).collect();
        paths.sort();
        assert_eq!(paths, vec!["/exposed", "/ns/ns_subdir", "/out", "/runtime", "/svc"]);

        // Make sure that the correct directories were mapped to the correct paths.
        for entry in ns {
            let dir = entry.directory.into_proxy().unwrap();
            let entries = fuchsia_fs::directory::readdir(&dir).await.unwrap();

            // These directories must contain a file with the same name
            let path = PathBuf::from(entry.path);
            let expected_file_name = path.file_name().unwrap().to_str().unwrap().to_string();
            assert_eq!(
                entries,
                vec![fuchsia_fs::directory::DirEntry {
                    name: expected_file_name,
                    kind: fuchsia_fs::directory::DirentKind::File
                }]
            );
        }
    }

    #[fuchsia::test]
    async fn nest_all_instance_dirs_resolved() {
        let exposed_dir = create_temp_dir("exposed");
        let svc_dir = create_temp_dir("svc");
        let ns_entries = create_ns_entries();

        let ns = nest_all_instance_dirs(ns_entries, exposed_dir, svc_dir, None, None);
        assert_eq!(ns.len(), 3);

        let mut paths: Vec<String> = ns.iter().map(|n| n.path.clone()).collect();
        paths.sort();
        assert_eq!(paths, vec!["/exposed", "/ns/ns_subdir", "/svc"]);

        // Make sure that the correct directories were mapped to the correct paths.
        for entry in ns {
            let dir = entry.directory.into_proxy().unwrap();
            let entries = fuchsia_fs::directory::readdir(&dir).await.unwrap();

            // These directories must contain a file with the same name
            let path = PathBuf::from(entry.path);
            let expected_file_name = path.file_name().unwrap().to_str().unwrap().to_string();
            assert_eq!(
                entries,
                vec![fuchsia_fs::directory::DirEntry {
                    name: expected_file_name,
                    kind: fuchsia_fs::directory::DirentKind::File
                }]
            );
        }
    }

    #[fuchsia::test]
    async fn instance_namespace_is_root_resolved() {
        let ns_entries = create_ns_entries();

        let ns = instance_namespace_is_root(ns_entries).await;

        let mut paths: Vec<String> = ns.iter().map(|n| n.path.clone()).collect();
        paths.sort();
        assert_eq!(paths, vec!["/ns_subdir"]);

        // Make sure that the correct directories were mapped to the correct paths.
        for entry in ns {
            let dir = entry.directory.into_proxy().unwrap();
            let entries = fuchsia_fs::directory::readdir(&dir).await.unwrap();

            // These directories must contain a file with the same name
            let path = PathBuf::from(entry.path);
            let expected_file_name = path.file_name().unwrap().to_str().unwrap().to_string();
            assert_eq!(
                entries,
                vec![fuchsia_fs::directory::DirEntry {
                    name: expected_file_name,
                    kind: fuchsia_fs::directory::DirentKind::File
                }]
            );
        }
    }
}
