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

//! Utilities for validating packages and components, separate from the `assembly_validate_product`
//! crate so they can be depended upon by libraries used to implement product validation.

use std::{
    collections::BTreeMap,
    error::Error,
    fmt::{Debug, Display},
    io::{Read, Seek},
    path::{Path, PathBuf},
};

mod inner_impl {
    use super::*;
    pub trait PkgNamespaceInner {
        /// Error type returned by namespace lookups/reads.
        type Err: Debug + Display + Error + Send + Sync + 'static;

        /// Read the contents of `path`.
        fn read_impl(&mut self, path: &str) -> Result<Vec<u8>, Self::Err>;
    }
}
use inner_impl::PkgNamespaceInner;

/// A type which can be used to describe the `/pkg` directory in a component's namespace.
pub trait PkgNamespace: PkgNamespaceInner {
    /// Return a list of all paths in the package visible to the component.
    fn paths(&self) -> Vec<String>;

    fn read_file(&mut self, path: &str) -> Result<Vec<u8>, ReadError> {
        match self.read_impl(path) {
            Ok(b) => Ok(b),
            Err(e) => {
                let same_ext_alternatives = if let Some((_, extension)) = path.rsplit_once('.') {
                    self.paths().into_iter().filter(|p| p.ends_with(extension)).collect()
                } else {
                    vec![]
                };
                Err(ReadError { inner: e.to_string(), same_ext_alternatives })
            }
        }
    }
}

#[derive(Debug)]
pub struct ReadError {
    inner: String,
    same_ext_alternatives: Vec<String>,
}

impl Display for ReadError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(&self.inner)?;

        if !self.same_ext_alternatives.is_empty() {
            f.write_str("\n\tPossible alternatives with the same extension: [")?;
            for path in &self.same_ext_alternatives {
                f.write_str("\n\t    ")?;
                f.write_str(path)?;
                f.write_str(",")?;
            }
            f.write_str("\n\t]")?;
        }

        Ok(())
    }
}

impl Error for ReadError {}

// NOTE: this implementation doesn't allow access to anything outside of `/pkg/meta`
impl<T> PkgNamespaceInner for fuchsia_archive::Utf8Reader<T>
where
    T: Read + Seek,
{
    type Err = fuchsia_archive::Error;

    fn read_impl(&mut self, path: &str) -> Result<Vec<u8>, Self::Err> {
        self.read_file(path)
    }
}

impl<T> PkgNamespace for fuchsia_archive::Utf8Reader<T>
where
    T: Read + Seek,
{
    fn paths(&self) -> Vec<String> {
        self.list().map(|e| e.path().to_owned()).collect()
    }
}

/// An in-memory representation of the bootfs for a given system image.
pub struct BootfsContents {
    files: BTreeMap<String, Vec<u8>>,
}

impl BootfsContents {
    pub fn from_iter(
        bootfs_files: impl Iterator<Item = (impl AsRef<str>, impl AsRef<Path>)>,
    ) -> Result<Self, BootfsContentsError> {
        let mut files = BTreeMap::new();
        for (dest, source) in bootfs_files {
            let source = source.as_ref();
            let contents = std::fs::read(source).map_err(|e| {
                BootfsContentsError::ReadSourceFile { path: source.to_owned(), source: e }
            })?;
            files.insert(dest.as_ref().to_owned(), contents);
        }
        Ok(Self { files })
    }
}

impl PkgNamespaceInner for BootfsContents {
    type Err = BootfsContentsError;

    fn read_impl(&mut self, path: &str) -> Result<Vec<u8>, Self::Err> {
        self.files
            .get(path)
            .map(|b| b.to_owned())
            .ok_or_else(|| BootfsContentsError::NoSuchFile(path.to_owned()))
    }
}

impl PkgNamespace for BootfsContents {
    fn paths(&self) -> Vec<String> {
        self.files.keys().cloned().collect()
    }
}

#[derive(Debug, thiserror::Error)]
pub enum BootfsContentsError {
    #[error("Failed to read `{}`.", path.display())]
    ReadSourceFile {
        path: PathBuf,
        #[source]
        source: std::io::Error,
    },
    #[error("`{_0}` does not exist in bootfs.")]
    NoSuchFile(String),
}
