// Copyright 2023 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, Result};
use assembly_platform_configuration::{DomainConfig, FileOrContents};
use assembly_util::FileEntry;
use camino::{Utf8Path, Utf8PathBuf};
use cml::RelativePath;
use fidl::persist;
use fuchsia_pkg::{PackageBuilder, PackageManifest, RelativeTo};
use std::io::Write;

/// A builder that takes domain configs and places them in a new package that
/// can be placed in the assembly.
pub struct DomainConfigPackage {
    config: DomainConfig,
}

impl DomainConfigPackage {
    /// Construct a new domain config package.
    pub fn new(config: DomainConfig) -> Self {
        Self { config }
    }

    /// Build the package and return the package manifest and path to manifest.
    pub fn build(self, outdir: impl AsRef<Utf8Path>) -> Result<(Utf8PathBuf, PackageManifest)> {
        let outdir = outdir.as_ref();
        std::fs::create_dir_all(&outdir)
            .with_context(|| format!("creating directory {}", &outdir))?;

        // Domain config packages are never produced by assembly tools from one
        // Fuchsia release and then read by binaries from another Fuchsia
        // release. Give them the platform ABI revision.
        let mut builder =
            PackageBuilder::new_platform_internal_package(&self.config.name.to_string());

        let manifest_path = outdir.join("package_manifest.json");
        let metafar_path = outdir.join("meta.far");
        builder.manifest_path(&manifest_path);
        builder.manifest_blobs_relative_to(RelativeTo::File);

        // Find all the directory routes to expose.
        let mut exposes = vec![];
        for (directory, directory_config) in self.config.directories {
            let subdir = RelativePath::new(&format!("meta/fuchsia.domain_config/{}", directory))
                .with_context(|| format!("Calculating relative path for {directory}"))?;
            let name = cml::Name::new(&directory)
                .with_context(|| format!("Calculating name for {directory}"))?;
            exposes.push(cml::Expose {
                // unwrap is safe, because try_new cannot fail with "pkg".
                directory: Some(cml::OneOrMany::One(cml::Name::new("pkg").unwrap())),
                r#as: Some(name),
                subdir: Some(subdir),
                ..cml::Expose::new_from(cml::OneOrMany::One(cml::ExposeFromRef::Framework))
            });

            if directory_config.entries.is_empty() {
                // Add an empty file to the directory to ensure the directory gets created.
                let empty_file_name = "_ensure_directory_creation";
                let empty_file_path = outdir.join(empty_file_name);
                let destination = Utf8PathBuf::from("meta/fuchsia.domain_config")
                    .join(&directory)
                    .join(empty_file_name);
                std::fs::write(&empty_file_path, "").context("writing empty file")?;
                builder
                    .add_file_to_far(destination, &empty_file_path)
                    .with_context(|| format!("adding empty file {empty_file_path}"))?;
            }

            // Add the necessary config files to the directory.
            for (destination, entry) in directory_config.entries {
                let destination = Utf8PathBuf::from("meta/fuchsia.domain_config")
                    .join(&directory)
                    .join(destination);
                match entry {
                    FileOrContents::File(FileEntry { source, .. }) => {
                        builder
                            .add_file_to_far(destination, &source)
                            .with_context(|| format!("adding config {source}"))?;
                    }
                    FileOrContents::Contents(contents) => {
                        builder
                            .add_contents_to_far(&destination, &contents, &outdir)
                            .with_context(|| format!("adding config to {destination}"))?;
                    }
                }
            }
        }

        if self.config.expose_directories {
            let cml = cml::Document { expose: Some(exposes), ..Default::default() };
            let out_data = cml::compile(&cml, cml::CompileOptions::default())
                .with_context(|| format!("compiling domain config routes"))?;
            let cm_name = format!("{}.cm", &self.config.name);
            let cm_path = outdir.join(&cm_name);
            let mut cm_file = std::fs::File::create(&cm_path)
                .with_context(|| format!("creating domain config routes: {cm_path}"))?;
            cm_file
                .write_all(&persist(&out_data)?)
                .with_context(|| format!("writing domain config routes: {cm_path}"))?;
            builder
                .add_file_to_far(format!("meta/{cm_name}"), &cm_path)
                .with_context(|| format!("adding file to domain config package: {cm_path}"))?;
        }

        let manifest = builder
            .build(&outdir, metafar_path)
            .with_context(|| format!("building domain config package: {}", &self.config.name))?;
        Ok((manifest_path, manifest))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assembly_platform_configuration::DomainConfigDirectory;
    use assembly_util::{NamedMap, PackageDestination, PackageSetDestination};
    use assert_matches::assert_matches;
    use cm_rust::{ComponentDecl, ExposeDecl, ExposeDirectoryDecl, ExposeSource, ExposeTarget};
    use fidl::unpersist;
    use fidl_fuchsia_component_decl::Component;
    use fuchsia_archive::Utf8Reader;
    use fuchsia_pkg::PackageName;
    use pretty_assertions::assert_eq;
    use std::fs::File;
    use std::str::FromStr;
    use tempfile::tempdir;

    #[test]
    fn build() {
        let tmp = tempdir().unwrap();
        let outdir = Utf8Path::from_path(tmp.path()).unwrap();

        // Prepare the domain config input.
        let config_source = outdir.join("config_source.json");
        std::fs::write(&config_source, "bleep bloop").unwrap();
        let mut entries = NamedMap::<String, FileOrContents>::new("config files");
        entries
            .try_insert_unique(
                "config.json".to_string(),
                FileOrContents::File(FileEntry {
                    source: config_source.clone(),
                    destination: "config.json".into(),
                }),
            )
            .unwrap();
        let config = DomainConfig {
            name: PackageSetDestination::Blob(PackageDestination::ForTest),
            directories: [("config-dir".into(), DomainConfigDirectory { entries })].into(),
            expose_directories: true,
        };

        let package = DomainConfigPackage::new(config);
        let (path, manifest) = package.build(&outdir).unwrap();

        // Assert the manifest is correct.
        assert_eq!(path, outdir.join("package_manifest.json"));
        let loaded_manifest = PackageManifest::try_load_from(path).unwrap();
        assert_eq!(manifest, loaded_manifest);
        assert_eq!(manifest.name(), &PackageName::from_str("for-test").unwrap());
        let blobs = manifest.into_blobs();
        assert_eq!(blobs.len(), 1);
        let blob = blobs.iter().find(|&b| &b.path == "meta/").unwrap();
        assert_eq!(blob.source_path, outdir.join("meta.far").to_string());

        // Assert the contents of the package are correct.
        let far_path = outdir.join("meta.far");
        let mut far_reader = Utf8Reader::new(File::open(&far_path).unwrap()).unwrap();
        let package = far_reader.read_file("meta/package").unwrap();
        assert_eq!(package, br#"{"name":"for-test","version":"0"}"#);
        let cm_bytes = far_reader.read_file("meta/for-test.cm").unwrap();
        let fidl_component_decl: Component = unpersist(&cm_bytes).unwrap();
        let component = ComponentDecl::try_from(fidl_component_decl).unwrap();
        assert_eq!(component.exposes.len(), 1);
        assert_matches!(&component.exposes[0], ExposeDecl::Directory(ExposeDirectoryDecl {
            source: ExposeSource::Framework,
            source_name,
            source_dictionary,
            target: ExposeTarget::Parent,
            target_name,
            rights: _,
            subdir,
            availability: _,
        }) => {
            assert_eq!(source_name, &cml::Name::new("pkg").unwrap());
            assert!(source_dictionary.is_dot());
            assert_eq!(target_name, &cml::Name::new("config-dir").unwrap());
            assert_eq!(subdir, &RelativePath::new("meta/fuchsia.domain_config/config-dir").unwrap());
        });
        let contents = far_reader.read_file("meta/contents").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "\
        "
        .to_string();
        assert_eq!(expected_contents, contents);
        let contents =
            far_reader.read_file("meta/fuchsia.domain_config/config-dir/config.json").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "bleep bloop".to_string();
        assert_eq!(expected_contents, contents);
    }

    #[test]
    fn build_no_routing() {
        let tmp = tempdir().unwrap();
        let outdir = Utf8Path::from_path(tmp.path()).unwrap();

        // Prepare the domain config input.
        let config_source = outdir.join("config_source.json");
        std::fs::write(&config_source, "bleep bloop").unwrap();
        let mut entries = NamedMap::<String, FileOrContents>::new("config files");
        entries
            .try_insert_unique(
                "config.json".to_string(),
                FileOrContents::File(FileEntry {
                    source: config_source.clone(),
                    destination: "config.json".into(),
                }),
            )
            .unwrap();
        let config = DomainConfig {
            name: PackageSetDestination::Blob(PackageDestination::ForTest),
            directories: [("config-dir".into(), DomainConfigDirectory { entries })].into(),
            expose_directories: false,
        };

        let package = DomainConfigPackage::new(config);
        let (path, manifest) = package.build(&outdir).unwrap();

        // Assert the manifest is correct.
        assert_eq!(path, outdir.join("package_manifest.json"));
        let loaded_manifest = PackageManifest::try_load_from(path).unwrap();
        assert_eq!(manifest, loaded_manifest);
        assert_eq!(manifest.name(), &PackageName::from_str("for-test").unwrap());
        let blobs = manifest.into_blobs();
        assert_eq!(blobs.len(), 1);
        let blob = blobs.iter().find(|&b| &b.path == "meta/").unwrap();
        assert_eq!(blob.source_path, outdir.join("meta.far").to_string());

        // Assert the contents of the package are correct.
        let far_path = outdir.join("meta.far");
        let mut far_reader = Utf8Reader::new(File::open(&far_path).unwrap()).unwrap();
        let package = far_reader.read_file("meta/package").unwrap();
        assert_eq!(package, br#"{"name":"for-test","version":"0"}"#);
        let contents = far_reader.read_file("meta/contents").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "\
        "
        .to_string();
        assert_eq!(expected_contents, contents);
        let contents =
            far_reader.read_file("meta/fuchsia.domain_config/config-dir/config.json").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "bleep bloop".to_string();
        assert_eq!(expected_contents, contents);
    }

    #[test]
    fn build_no_directories() {
        let tmp = tempdir().unwrap();
        let outdir = Utf8Path::from_path(tmp.path()).unwrap();

        // Prepare the domain config input.
        let config = DomainConfig {
            name: PackageSetDestination::Blob(PackageDestination::ForTest),
            directories: NamedMap::new("directories"),
            expose_directories: true,
        };
        let package = DomainConfigPackage::new(config);
        let (path, manifest) = package.build(&outdir).unwrap();

        // Assert the manifest is correct.
        assert_eq!(path, outdir.join("package_manifest.json"));
        let loaded_manifest = PackageManifest::try_load_from(path).unwrap();
        assert_eq!(manifest, loaded_manifest);
        assert_eq!(manifest.name(), &PackageName::from_str("for-test").unwrap());
        let blobs = manifest.into_blobs();
        assert_eq!(blobs.len(), 1);
        let blob = blobs.iter().find(|&b| b.path == "meta/").unwrap();
        assert_eq!(blob.source_path, outdir.join("meta.far").to_string());

        // Assert the contents of the package are correct.
        let far_path = outdir.join("meta.far");
        let mut far_reader = Utf8Reader::new(File::open(&far_path).unwrap()).unwrap();
        let package = far_reader.read_file("meta/package").unwrap();
        assert_eq!(package, br#"{"name":"for-test","version":"0"}"#);
        let cm_bytes = far_reader.read_file("meta/for-test.cm").unwrap();
        let fidl_component_decl: Component = unpersist(&cm_bytes).unwrap();
        let component = ComponentDecl::try_from(fidl_component_decl).unwrap();
        assert_eq!(component.exposes.len(), 0);
        let contents = far_reader.read_file("meta/contents").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "\
        "
        .to_string();
        assert_eq!(expected_contents, contents);
    }

    #[test]
    fn build_no_configs() {
        let tmp = tempdir().unwrap();
        let outdir = Utf8Path::from_path(tmp.path()).unwrap();

        // Prepare the domain config input.
        let entries = NamedMap::<String, FileOrContents>::new("config files");
        let config = DomainConfig {
            name: PackageSetDestination::Blob(PackageDestination::ForTest),
            directories: [("config-dir".into(), DomainConfigDirectory { entries })].into(),
            expose_directories: true,
        };

        let package = DomainConfigPackage::new(config);
        let (path, manifest) = package.build(&outdir).unwrap();

        // Assert the manifest is correct.
        assert_eq!(path, outdir.join("package_manifest.json"));
        let loaded_manifest = PackageManifest::try_load_from(path).unwrap();
        assert_eq!(manifest, loaded_manifest);
        assert_eq!(manifest.name(), &PackageName::from_str("for-test").unwrap());
        let blobs = manifest.into_blobs();
        assert_eq!(blobs.len(), 1);
        let blob = blobs.iter().find(|&b| &b.path == "meta/").unwrap();
        assert_eq!(blob.source_path, outdir.join("meta.far").to_string());

        // Assert the contents of the package are correct.
        let far_path = outdir.join("meta.far");
        let mut far_reader = Utf8Reader::new(File::open(&far_path).unwrap()).unwrap();
        let package = far_reader.read_file("meta/package").unwrap();
        assert_eq!(package, br#"{"name":"for-test","version":"0"}"#);
        let cm_bytes = far_reader.read_file("meta/for-test.cm").unwrap();
        let fidl_component_decl: Component = unpersist(&cm_bytes).unwrap();
        let component = ComponentDecl::try_from(fidl_component_decl).unwrap();
        assert_eq!(component.exposes.len(), 1);
        assert_matches!(&component.exposes[0], ExposeDecl::Directory(ExposeDirectoryDecl {
            source: ExposeSource::Framework,
            source_name,
            source_dictionary,
            target: ExposeTarget::Parent,
            target_name,
            rights: _,
            subdir,
            availability: _,
        }) => {
            assert_eq!(source_name, &cml::Name::new("pkg").unwrap());
            assert!(source_dictionary.is_dot());
            assert_eq!(target_name, &cml::Name::new("config-dir").unwrap());
            assert_eq!(subdir, &RelativePath::new("meta/fuchsia.domain_config/config-dir").unwrap());
        });
        let contents = far_reader.read_file("meta/contents").unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "\
        "
        .to_string();
        assert_eq!(expected_contents, contents);
        let contents = far_reader
            .read_file("meta/fuchsia.domain_config/config-dir/_ensure_directory_creation")
            .unwrap();
        let contents = std::str::from_utf8(&contents).unwrap();
        let expected_contents = "".to_string();
        assert_eq!(expected_contents, contents);
    }
}
