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

//! Typesafe wrappers around the /pkgfs/packages filesystem.

use {
    fidl_fuchsia_io::{DirectoryMarker, DirectoryProxy, DirectoryRequestStream},
    fuchsia_zircon::Status,
    thiserror::Error,
};

/// An error encountered while opening a package
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum OpenError {
    #[error("the package does not exist")]
    NotFound,

    #[error("while opening the package")]
    Io(#[source] io_util::node::OpenError),
}

/// An open handle to /pkgfs/packages
#[derive(Debug, Clone)]
pub struct Client {
    proxy: DirectoryProxy,
}

impl Client {
    /// Returns an client connected to pkgfs from the current component's namespace
    pub fn open_from_namespace() -> Result<Self, io_util::node::OpenError> {
        let proxy = io_util::directory::open_in_namespace(
            "/pkgfs/packages",
            fidl_fuchsia_io::OPEN_RIGHT_READABLE,
        )?;
        Ok(Client { proxy })
    }

    /// Returns an client connected to pkgfs from the given pkgfs root dir.
    pub fn open_from_pkgfs_root(pkgfs: &DirectoryProxy) -> Result<Self, io_util::node::OpenError> {
        Ok(Client {
            proxy: io_util::directory::open_directory_no_describe(
                pkgfs,
                "packages",
                fidl_fuchsia_io::OPEN_RIGHT_READABLE,
            )?,
        })
    }

    /// Creates a new client backed by the returned request stream. This constructor should not be
    /// used outside of tests.
    ///
    /// # Panics
    ///
    /// Panics on error
    pub fn new_test() -> (Self, DirectoryRequestStream) {
        let (proxy, stream) =
            fidl::endpoints::create_proxy_and_stream::<DirectoryMarker>().unwrap();

        (Self { proxy }, stream)
    }

    /// Open the package given by `name` and `variant` (defaults to "0"). Verifies the OnOpen event
    /// before returning.
    pub async fn open_package(
        &self,
        name: &str,
        variant: Option<&str>,
    ) -> Result<fuchsia_pkg::PackageDirectory, OpenError> {
        // TODO(fxbug.dev/37858) allow opening as executable too
        let flags = fidl_fuchsia_io::OPEN_RIGHT_READABLE;
        let path = format!("{}/{}", name, variant.unwrap_or("0"));
        let dir = io_util::directory::open_directory(&self.proxy, &path, flags).await.map_err(
            |e| match e {
                io_util::node::OpenError::OpenError(Status::NOT_FOUND) => OpenError::NotFound,
                other => OpenError::Io(other),
            },
        )?;

        Ok(fuchsia_pkg::PackageDirectory::from_proxy(dir))
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*, crate::install::BlobKind, fuchsia_pkg_testing::PackageBuilder,
        matches::assert_matches, pkgfs_ramdisk::PkgfsRamdisk,
    };

    #[fuchsia_async::run_singlethreaded(test)]
    async fn open_non_existant_package_fails() {
        let pkgfs = PkgfsRamdisk::start().unwrap();
        let root = pkgfs.root_dir_proxy().unwrap();
        let client = Client::open_from_pkgfs_root(&root).unwrap();

        assert_matches!(client.open_package("fake", None).await, Err(OpenError::NotFound));
        assert_matches!(
            client.open_package("fake", Some("package")).await,
            Err(OpenError::NotFound)
        );

        pkgfs.stop().await.unwrap();
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn open_package_single_blob() {
        let pkgfs =
            PkgfsRamdisk::builder().enforce_packages_non_static_allowlist(false).start().unwrap();
        let root = pkgfs.root_dir_proxy().unwrap();
        let install = crate::install::Client::open_from_pkgfs_root(&root).unwrap();
        let client = Client::open_from_pkgfs_root(&root).unwrap();

        let pkg = PackageBuilder::new("uniblob").build().await.unwrap();
        install.write_meta_far(&pkg).await;

        assert_matches!(client.open_package("uniblob", None).await, Ok(_));
        assert_matches!(
            pkg.verify_contents(
                &client.open_package("uniblob", Some("0")).await.unwrap().into_proxy()
            )
            .await,
            Ok(())
        );

        pkgfs.stop().await.unwrap();
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn open_package_multiple_blobs() {
        let pkgfs =
            PkgfsRamdisk::builder().enforce_packages_non_static_allowlist(false).start().unwrap();
        let root = pkgfs.root_dir_proxy().unwrap();
        let install = crate::install::Client::open_from_pkgfs_root(&root).unwrap();
        let client = Client::open_from_pkgfs_root(&root).unwrap();

        let pkg = PackageBuilder::new("multiblob")
            .add_resource_at("data/first", "contents of first blob".as_bytes())
            .add_resource_at("data/second", "contents of second blob".as_bytes())
            .build()
            .await
            .unwrap();
        let pkg_contents = pkg.meta_contents().unwrap().contents().to_owned();
        install.write_meta_far(&pkg).await;

        // Package is not complete yet, so opening fails.
        assert_matches!(client.open_package("multiblob", None).await, Err(OpenError::NotFound));

        install
            .write_blob(
                pkg_contents["data/first"],
                BlobKind::Data,
                "contents of first blob".as_bytes(),
            )
            .await;
        install
            .write_blob(
                pkg_contents["data/second"],
                BlobKind::Data,
                "contents of second blob".as_bytes(),
            )
            .await;

        assert_matches!(client.open_package("multiblob", None).await, Ok(_));
        assert_matches!(
            pkg.verify_contents(
                &client.open_package("multiblob", Some("0")).await.unwrap().into_proxy()
            )
            .await,
            Ok(())
        );

        pkgfs.stop().await.unwrap();
    }
}
