// 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 {
    fidl::endpoints::ServerEnd,
    fidl_fuchsia_io as fio, fuchsia_zircon as zx,
    std::{collections::HashSet, convert::TryInto as _, sync::Arc},
    vfs::{
        common::send_on_open_with_error,
        directory::entry::{DirectoryEntry, EntryInfo},
        path::Path as VfsPath,
    },
};

mod meta_as_dir;
mod meta_as_file;
mod meta_file;
mod meta_subdir;
mod non_meta_subdir;
mod root_dir;

pub use root_dir::{ReadFileError, RootDir};
pub use vfs::execution_scope::ExecutionScope;

#[derive(thiserror::Error, Debug)]
pub enum Error {
    #[error("while opening the meta.far")]
    OpenMetaFar(#[source] io_util::node::OpenError),

    #[error("while instantiating a fuchsia archive reader")]
    ArchiveReader(#[source] fuchsia_archive::Error),

    #[error("while reading meta/contents")]
    ReadMetaContents(#[source] fuchsia_archive::Error),

    #[error("while deserializing meta/contents")]
    DeserializeMetaContents(#[source] fuchsia_pkg::MetaContentsError),

    #[error("collision between a file and a directory at path: '{:?}'", path)]
    FileDirectoryCollision { path: String },
}

impl Error {
    fn to_zx_status(&self) -> zx::Status {
        use io_util::node::OpenError;

        // TODO(fxbug.dev/86995) Align this mapping with pkgfs.
        match self {
            Error::OpenMetaFar(OpenError::OpenError(s)) => *s,
            Error::OpenMetaFar(_) => zx::Status::INTERNAL,
            Error::ArchiveReader(fuchsia_archive::Error::Read(_)) => zx::Status::NOT_FOUND,
            Error::ArchiveReader(_)
            | Error::ReadMetaContents(_)
            | Error::DeserializeMetaContents(_) => zx::Status::INVALID_ARGS,
            Error::FileDirectoryCollision { .. } => zx::Status::INVALID_ARGS,
        }
    }
}

/// Serves a package directory for the package with hash `meta_far` on `server_end`.
/// The connection rights are set by `flags`, used the same as the `flags` parameter of
///   fuchsia.io/Directory.Open.
pub fn serve(
    scope: vfs::execution_scope::ExecutionScope,
    blobfs: blobfs::Client,
    meta_far: fuchsia_hash::Hash,
    flags: fio::OpenFlags,
    server_end: ServerEnd<fio::DirectoryMarker>,
) -> impl futures::Future<Output = Result<(), Error>> {
    serve_path(scope, blobfs, meta_far, flags, 0, VfsPath::dot(), server_end.into_channel().into())
}

/// Serves a sub-`path` of a package directory for the package with hash `meta_far` on `server_end`.
/// The connection rights are set by `flags`, used the same as the `flags` parameter of
///   fuchsia.io/Directory.Open.
/// On error while loading the package metadata, closes the provided server end, sending an OnOpen
///   response with an error status if requested.
pub async fn serve_path(
    scope: vfs::execution_scope::ExecutionScope,
    blobfs: blobfs::Client,
    meta_far: fuchsia_hash::Hash,
    flags: fio::OpenFlags,
    mode: u32,
    path: VfsPath,
    server_end: ServerEnd<fio::NodeMarker>,
) -> Result<(), Error> {
    let root_dir = match RootDir::new(blobfs, meta_far).await {
        Ok(d) => d,
        Err(e) => {
            let () = send_on_open_with_error(flags, server_end, e.to_zx_status());
            return Err(e);
        }
    };

    Ok(Arc::new(root_dir).open(scope, flags, mode, path, server_end))
}

fn usize_to_u64_safe(u: usize) -> u64 {
    let ret: u64 = u.try_into().unwrap();
    static_assertions::assert_eq_size_val!(u, ret);
    ret
}

fn u64_to_usize_safe(u: u64) -> usize {
    let ret: usize = u.try_into().unwrap();
    static_assertions::assert_eq_size_val!(u, ret);
    ret
}

/// Takes a directory hierarchy and a directory in the hierarchy and returns all the directory's
/// children in alphabetical order.
///   `materialized_tree`: object relative path expressions of every file in a directory hierarchy
///   `dir`: the empty string (signifies the root dir) or a path to a subdir (must be an object
///          relative path expression plus a trailing slash)
/// Returns an empty vec if `dir` isn't in `materialized_tree`.
fn get_dir_children<'a>(
    materialized_tree: impl IntoIterator<Item = &'a str>,
    dir: &str,
) -> Vec<(EntryInfo, String)> {
    let mut added_entries = HashSet::new();
    let mut res = vec![];

    for path in materialized_tree {
        if let Some(path) = path.strip_prefix(&dir) {
            match path.split_once("/") {
                None => {
                    // TODO(fxbug.dev/81370) Replace .contains/.insert with .get_or_insert_owned when non-experimental.
                    if !added_entries.contains(path) {
                        res.push((
                            EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::File),
                            path.to_string(),
                        ));
                        added_entries.insert(path.to_string());
                    }
                }
                Some((first, _)) => {
                    if !added_entries.contains(first) {
                        res.push((
                            EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::Directory),
                            first.to_string(),
                        ));
                        added_entries.insert(first.to_string());
                    }
                }
            }
        }
    }

    // TODO(fxbug.dev/82290) Remove this sort
    res.sort_by(|a, b| a.1.cmp(&b.1));
    res
}

#[cfg(test)]
async fn verify_open_adjusts_flags(
    entry: &Arc<dyn DirectoryEntry>,
    in_flags: fio::OpenFlags,
    expected_flags: fio::OpenFlags,
) {
    let (proxy, server_end) = fidl::endpoints::create_proxy::<fio::NodeMarker>().unwrap();

    DirectoryEntry::open(
        Arc::clone(&entry),
        ExecutionScope::new(),
        in_flags,
        0,
        VfsPath::dot(),
        server_end,
    );

    let (status, flags) = proxy.get_flags().await.unwrap();
    let () = zx::Status::ok(status).unwrap();
    assert_eq!(flags, expected_flags);
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        assert_matches::assert_matches,
        fuchsia_hash::Hash,
        fuchsia_pkg_testing::{blobfs::Fake as FakeBlobfs, PackageBuilder},
        futures::StreamExt,
        std::any::Any,
        vfs::directory::dirents_sink::{self, AppendResult, Sealed, Sink},
    };

    #[fuchsia_async::run_singlethreaded(test)]
    async fn serve() {
        let (proxy, server_end) = fidl::endpoints::create_proxy().unwrap();
        let package = PackageBuilder::new("just-meta-far").build().await.expect("created pkg");
        let (metafar_blob, _) = package.contents();
        let (blobfs_fake, blobfs_client) = FakeBlobfs::new();
        blobfs_fake.add_blob(metafar_blob.merkle, metafar_blob.contents);

        crate::serve(
            vfs::execution_scope::ExecutionScope::new(),
            blobfs_client,
            metafar_blob.merkle,
            fio::OpenFlags::RIGHT_READABLE,
            server_end,
        )
        .await
        .unwrap();

        assert_eq!(
            files_async::readdir(&proxy).await.unwrap(),
            vec![files_async::DirEntry {
                name: "meta".to_string(),
                kind: files_async::DirentKind::Directory
            }]
        );
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn serve_path_open_root() {
        let (proxy, server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>().unwrap();
        let package = PackageBuilder::new("just-meta-far").build().await.expect("created pkg");
        let (metafar_blob, _) = package.contents();
        let (blobfs_fake, blobfs_client) = FakeBlobfs::new();
        blobfs_fake.add_blob(metafar_blob.merkle, metafar_blob.contents);

        crate::serve_path(
            vfs::execution_scope::ExecutionScope::new(),
            blobfs_client,
            metafar_blob.merkle,
            fio::OpenFlags::RIGHT_READABLE,
            0,
            VfsPath::validate_and_split(".").unwrap(),
            server_end.into_channel().into(),
        )
        .await
        .unwrap();

        assert_eq!(
            files_async::readdir(&proxy).await.unwrap(),
            vec![files_async::DirEntry {
                name: "meta".to_string(),
                kind: files_async::DirentKind::Directory
            }]
        );
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn serve_path_open_meta() {
        let (proxy, server_end) = fidl::endpoints::create_proxy::<fio::FileMarker>().unwrap();
        let package = PackageBuilder::new("just-meta-far").build().await.expect("created pkg");
        let (metafar_blob, _) = package.contents();
        let (blobfs_fake, blobfs_client) = FakeBlobfs::new();
        blobfs_fake.add_blob(metafar_blob.merkle, metafar_blob.contents);

        crate::serve_path(
            vfs::execution_scope::ExecutionScope::new(),
            blobfs_client,
            metafar_blob.merkle,
            fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::NOT_DIRECTORY,
            0,
            VfsPath::validate_and_split("meta").unwrap(),
            server_end.into_channel().into(),
        )
        .await
        .unwrap();

        assert_eq!(
            io_util::file::read_to_string(&proxy).await.unwrap(),
            metafar_blob.merkle.to_string(),
        );
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn serve_path_open_missing_path_in_package() {
        let (proxy, server_end) = fidl::endpoints::create_proxy::<fio::NodeMarker>().unwrap();
        let package = PackageBuilder::new("just-meta-far").build().await.expect("created pkg");
        let (metafar_blob, _) = package.contents();
        let (blobfs_fake, blobfs_client) = FakeBlobfs::new();
        blobfs_fake.add_blob(metafar_blob.merkle, metafar_blob.contents);

        assert_matches!(
            crate::serve_path(
                vfs::execution_scope::ExecutionScope::new(),
                blobfs_client,
                metafar_blob.merkle,
                fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DESCRIBE,
                0,
                VfsPath::validate_and_split("not-present").unwrap(),
                server_end.into_channel().into(),
            )
            .await,
            // serve_path succeeds in opening the package, but the forwarded open will discover
            // that the requested path does not exist.
            Ok(())
        );

        assert_eq!(node_into_on_open_status(proxy).await, Some(zx::Status::NOT_FOUND));
    }

    #[fuchsia_async::run_singlethreaded(test)]
    async fn serve_path_open_missing_package() {
        let (proxy, server_end) = fidl::endpoints::create_proxy::<fio::NodeMarker>().unwrap();
        let (_blobfs_fake, blobfs_client) = FakeBlobfs::new();

        assert_matches!(
            crate::serve_path(
                vfs::execution_scope::ExecutionScope::new(),
                blobfs_client,
                Hash::from([0u8; 32]),
                fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::DESCRIBE,
                0,
                VfsPath::validate_and_split(".").unwrap(),
                server_end.into_channel().into(),
            )
            .await,
            // RootDir opens the meta.far without requesting an OnOpen event, which improves
            // latency, but results in a less-than-ideal error (a PEER_CLOSED while reading from
            // the meta.far).
            Err(Error::ArchiveReader(_))
        );

        assert_eq!(node_into_on_open_status(proxy).await, Some(zx::Status::NOT_FOUND));
    }

    async fn node_into_on_open_status(node: fio::NodeProxy) -> Option<zx::Status> {
        // Handle either an io1 OnOpen Status or an io2 epitaph status, though only one will be
        // sent, determined by the open() API used.
        let mut events = node.take_event_stream();
        match events.next().await? {
            Ok(fio::NodeEvent::OnOpen_ { s: status, .. }) => {
                return Some(zx::Status::from_raw(status));
            }
            Ok(fio::NodeEvent::OnConnectionInfo { .. }) => return Some(zx::Status::OK),
            Err(fidl::Error::ClientChannelClosed { status, .. }) => return Some(status),
            other => panic!("unexpected stream event or error: {:?}", other),
        }
    }

    fn file() -> EntryInfo {
        EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::File)
    }

    fn dir() -> EntryInfo {
        EntryInfo::new(fio::INO_UNKNOWN, fio::DirentType::Directory)
    }

    #[test]
    fn get_dir_children_root() {
        assert_eq!(get_dir_children([], ""), vec![]);
        assert_eq!(get_dir_children(["a"], ""), vec![(file(), "a".to_string())]);
        assert_eq!(
            get_dir_children(["a", "b"], ""),
            vec![(file(), "a".to_string()), (file(), "b".to_string())]
        );
        assert_eq!(
            get_dir_children(["b", "a"], ""),
            vec![(file(), "a".to_string()), (file(), "b".to_string())]
        );
        assert_eq!(get_dir_children(["a", "a"], ""), vec![(file(), "a".to_string())]);
        assert_eq!(get_dir_children(["a/b"], ""), vec![(dir(), "a".to_string())]);
        assert_eq!(
            get_dir_children(["a/b", "c"], ""),
            vec![(dir(), "a".to_string()), (file(), "c".to_string())]
        );
        assert_eq!(get_dir_children(["a/b/c"], ""), vec![(dir(), "a".to_string())]);
    }

    #[test]
    fn get_dir_children_subdir() {
        assert_eq!(get_dir_children([], "a/"), vec![]);
        assert_eq!(get_dir_children(["a"], "a/"), vec![]);
        assert_eq!(get_dir_children(["a", "b"], "a/"), vec![]);
        assert_eq!(get_dir_children(["a/b"], "a/"), vec![(file(), "b".to_string())]);
        assert_eq!(
            get_dir_children(["a/b", "a/c"], "a/"),
            vec![(file(), "b".to_string()), (file(), "c".to_string())]
        );
        assert_eq!(
            get_dir_children(["a/c", "a/b"], "a/"),
            vec![(file(), "b".to_string()), (file(), "c".to_string())]
        );
        assert_eq!(get_dir_children(["a/b", "a/b"], "a/"), vec![(file(), "b".to_string())]);
        assert_eq!(get_dir_children(["a/b/c"], "a/"), vec![(dir(), "b".to_string())]);
        assert_eq!(
            get_dir_children(["a/b/c", "a/d"], "a/"),
            vec![(dir(), "b".to_string()), (file(), "d".to_string())]
        );
        assert_eq!(get_dir_children(["a/b/c/d"], "a/"), vec![(dir(), "b".to_string())]);
    }

    /// Implementation of vfs::directory::dirents_sink::Sink.
    /// Sink::append begins to fail (returns Sealed) after `max_entries` entries have been appended.
    #[derive(Clone)]
    pub(crate) struct FakeSink {
        max_entries: usize,
        pub(crate) entries: Vec<(String, EntryInfo)>,
        sealed: bool,
    }

    impl FakeSink {
        pub(crate) fn new(max_entries: usize) -> Self {
            FakeSink { max_entries, entries: Vec::with_capacity(max_entries), sealed: false }
        }

        pub(crate) fn from_sealed(sealed: Box<dyn dirents_sink::Sealed>) -> Box<FakeSink> {
            sealed.into()
        }
    }

    impl From<Box<dyn dirents_sink::Sealed>> for Box<FakeSink> {
        fn from(sealed: Box<dyn dirents_sink::Sealed>) -> Self {
            sealed.open().downcast::<FakeSink>().unwrap()
        }
    }

    impl Sink for FakeSink {
        fn append(mut self: Box<Self>, entry: &EntryInfo, name: &str) -> AppendResult {
            assert!(!self.sealed);
            if self.entries.len() == self.max_entries {
                AppendResult::Sealed(self.seal())
            } else {
                self.entries.push((name.to_owned(), entry.clone()));
                AppendResult::Ok(self)
            }
        }

        fn seal(mut self: Box<Self>) -> Box<dyn Sealed> {
            self.sealed = true;
            self
        }
    }

    impl Sealed for FakeSink {
        fn open(self: Box<Self>) -> Box<dyn Any> {
            self
        }
    }
}
