// 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 {
    crate::blobfs::{BlobFsReader, BlobFsReaderBuilder},
    anyhow::{anyhow, Context, Result},
    log::warn,
    pathdiff::diff_paths,
    std::{
        collections::HashSet,
        fs::{self, File},
        io::{BufReader, Read, Seek},
        path::{Path, PathBuf},
    },
};

/// Interface for fetching raw bytes by file path.
pub trait ArtifactReader: Send + Sync {
    /// Read the raw bytes stored in filesystem location `path`.
    fn read_bytes(&mut self, path: &Path) -> Result<Vec<u8>>;

    /// Get the accumulated set of filesystem locations that have been read by
    /// this reader.
    fn get_deps(&self) -> HashSet<PathBuf>;
}

/// Implementation of `ArtifactReader` for blobfs archive files.
pub struct BlobFsArtifactReader<RS: Read + Seek> {
    blobfs_dep_path: PathBuf,
    blobfs_reader: BlobFsReader<RS>,
}

impl BlobFsArtifactReader<BufReader<File>> {
    /// Try to construct an artifact reader rooted at `build_path` that loads
    /// blobfs from the `build_path`-relative path `blobfs_path`.
    pub fn try_new<P1: AsRef<Path>, P2: AsRef<Path>>(
        build_path: P1,
        blobfs_path: P2,
    ) -> Result<Self> {
        let build_path_ref = build_path.as_ref();
        let blobfs_path_ref = blobfs_path.as_ref();
        let build_path = match build_path_ref.canonicalize() {
            Ok(path) => path,
            Err(err) => {
                warn!(
                    "Blobfs artifact reader failed to canonicalize build path: {:?}: {}",
                    build_path_ref,
                    err.to_string()
                );
                build_path_ref.to_path_buf()
            }
        };
        let blobfs_path = match blobfs_path_ref.canonicalize() {
            Ok(path) => path,
            Err(err) => {
                warn!(
                    "File artifact reader failed to canonicalize blobfs archive path: {:?}: {}",
                    blobfs_path_ref,
                    err.to_string()
                );
                blobfs_path_ref.to_path_buf()
            }
        };

        if !blobfs_path.is_absolute() {
            return Err(anyhow!("Blobfs archive path {:?} is not absolute", blobfs_path));
        }
        let blobfs_path_str = blobfs_path.to_str().ok_or_else(|| {
            anyhow!("Blobfs archive path {:?} could not be converted to string", blobfs_path)
        })?;
        let blobfs_dep_path =
            dep_from_absolute(&build_path, blobfs_path_str).with_context(|| {
                format!(
                    "Blobfs archive path {:?} could not be made relative to build path {:?}",
                    blobfs_path, build_path
                )
            })?;

        let blobfs_file = File::open(&blobfs_path)
            .map_err(|err| anyhow!("Failed to open blobfs archive {:?}: {}", blobfs_path, err))?;
        let blobfs_reader = BlobFsReaderBuilder::new()
            .archive(BufReader::new(blobfs_file))
            .context("Failed to prepare blobfs archive for artifact reader")?
            .build()
            .context("Failed to parse blobfs archive metadata for artifact reader")?;
        Ok(Self { blobfs_dep_path, blobfs_reader })
    }

    /// Try to construct a compound artifact reader that consults multiple
    /// blobfs archives (in the order specified by `blobfs_paths`) when reading
    /// artifacts.
    pub fn try_compound<P1: AsRef<Path>, P2: AsRef<Path>>(
        build_path: P1,
        blobfs_paths: &Vec<P2>,
    ) -> Result<CompoundArtifactReader> {
        Ok(CompoundArtifactReader::new(
            blobfs_paths
                .into_iter()
                .map(|blobfs_path| {
                    let reader = Self::try_new(&build_path, blobfs_path)?;
                    let boxed: Box<dyn ArtifactReader> = Box::new(reader);
                    Ok(boxed)
                })
                .collect::<Result<Vec<Box<dyn ArtifactReader>>>>()?,
        ))
    }
}

// `BlobfsArtifactReader` cannot be cloned in general, but the
// `<BufReader<File>>` must be clonable for some workflows.
impl Clone for BlobFsArtifactReader<BufReader<File>> {
    fn clone(&self) -> Self {
        Self {
            blobfs_dep_path: self.blobfs_dep_path.clone(),
            blobfs_reader: self.blobfs_reader.clone(),
        }
    }
}

impl<RS: Read + Seek + Send + Sync> ArtifactReader for BlobFsArtifactReader<RS> {
    fn read_bytes(&mut self, path: &Path) -> Result<Vec<u8>> {
        self.blobfs_reader.read_blob(path).with_context(|| {
            format!("Failed to read blob {:?} from blobfs via artifact reader", path)
        })
    }

    fn get_deps(&self) -> HashSet<PathBuf> {
        [self.blobfs_dep_path.clone()].into()
    }
}

/// An artifact reader that consults a sequence of delegate readers, returning
/// the first non-error result, or else an error describing all error results.
/// The dependencies tracked by this implementation is the union of all
/// delegates' dependencies.
pub struct CompoundArtifactReader {
    delegates: Vec<Box<dyn ArtifactReader>>,
}

impl CompoundArtifactReader {
    pub fn new(delegates: Vec<Box<dyn ArtifactReader>>) -> Self {
        Self { delegates }
    }
}

impl ArtifactReader for CompoundArtifactReader {
    fn read_bytes(&mut self, path: &Path) -> Result<Vec<u8>> {
        let mut errs = vec![];
        for delegate in self.delegates.iter_mut() {
            match delegate.read_bytes(path) {
                Ok(data) => {
                    return Ok(data);
                }
                Err(err) => {
                    errs.push(err);
                }
            }
        }
        let mut compound_err = anyhow!("Compound artifact read failed");
        for err in errs.into_iter() {
            compound_err = compound_err.context("Read failure");
            for ctx in err.chain() {
                compound_err = compound_err.context(ctx.to_string());
            }
        }
        Err(compound_err)
    }

    fn get_deps(&self) -> HashSet<PathBuf> {
        let mut deps = HashSet::new();
        for delegate in self.delegates.iter() {
            deps.extend(delegate.get_deps().into_iter());
        }
        deps
    }
}

impl From<Vec<BlobFsArtifactReader<BufReader<File>>>> for CompoundArtifactReader {
    fn from(readers: Vec<BlobFsArtifactReader<BufReader<File>>>) -> Self {
        Self::new(
            readers
                .iter()
                .map(|reader| Box::new(reader.clone()) as Box<dyn ArtifactReader>)
                .collect(),
        )
    }
}

/// An `ArtifactReader` implementation that reads paths relative to a particular
/// directory.
#[derive(Clone)]
pub struct FileArtifactReader {
    build_path: PathBuf,
    artifact_path: PathBuf,
    deps: HashSet<PathBuf>,
}

impl FileArtifactReader {
    /// Construct a new artifact reader that tracks dependencies relative to
    /// `build_path` and reads artifacts relative to `artifact_path`.
    pub fn new(build_path: &Path, artifact_path: &Path) -> Self {
        let build_path = match build_path.canonicalize() {
            Ok(path) => path,
            Err(err) => {
                warn!(
                    "File artifact reader failed to canonicalize build path: {:?}: {}",
                    build_path,
                    err.to_string()
                );
                build_path.to_path_buf()
            }
        };
        let artifact_path = match artifact_path.canonicalize() {
            Ok(path) => path,
            Err(err) => {
                warn!(
                    "File artifact reader failed to canonicalize artifact path: {:?}: {}",
                    artifact_path,
                    err.to_string()
                );
                artifact_path.to_path_buf()
            }
        };
        Self { build_path, artifact_path, deps: HashSet::new() }
    }
}

impl ArtifactReader for FileArtifactReader {
    fn read_bytes(&mut self, path: &Path) -> Result<Vec<u8>> {
        let absolute_path_string =
            absolute_from_absolute_or_artifact_relative(&self.artifact_path, path)
                .context("Absolute path conversion failure during read")?;
        let dep_path_string = dep_from_absolute(&self.build_path, &absolute_path_string)
            .context("Dep path conversion failed during read")?;
        self.deps.insert(dep_path_string);
        Ok(fs::read(&absolute_path_string).map_err(|err| {
            anyhow!("Artifact read failed ({}): {}", &absolute_path_string, err.to_string())
        })?)
    }

    fn get_deps(&self) -> HashSet<PathBuf> {
        self.deps.clone()
    }
}

fn absolute_from_absolute_or_artifact_relative<P1: AsRef<Path>, P2: AsRef<Path>>(
    artifact_path: P1,
    path: P2,
) -> Result<String> {
    let artifact_path_ref = artifact_path.as_ref();
    let path_ref = path.as_ref();
    let artifact_relative_path_buf = if path_ref.is_absolute() {
        diff_paths(path_ref, &artifact_path).ok_or_else(|| {
            anyhow!(
                "Absolute artifact path {:?} cannot be rebased to base artifact path {:?}",
                path_ref,
                artifact_path_ref,
            )
        })?
    } else {
        path_ref.to_path_buf()
    };
    let absolute_path_buf = artifact_path_ref.join(&artifact_relative_path_buf);
    let absolute_path_buf = absolute_path_buf.canonicalize().map_err(|err| {
        anyhow!(
            "Failed to canonicalize computed path: {:?}: {}",
            absolute_path_buf,
            err.to_string()
        )
    })?;

    if absolute_path_buf.is_relative() {
        return Err(anyhow!(
            "Computed artifact path is relative: computed {:?} from path {:?} and artifact base path {:?}",
            absolute_path_buf,
            path_ref,
            artifact_path_ref,
        ));
    }
    if absolute_path_buf.is_dir() {
        return Err(anyhow!(
            "Computed artifact path is directory: computed {:?} from path {:?} and artifact base path {:?}",
            absolute_path_buf,
            path_ref,
            artifact_path_ref,
        ));
    }

    let absolute_path_str = absolute_path_buf.to_str();
    if absolute_path_str.is_none() {
        return Err(anyhow!(
            "Computed absolute artifact path {:?} could not be converted to string",
            absolute_path_buf
        ));
    };
    Ok(absolute_path_str.unwrap().to_string())
}

fn dep_from_absolute<P1: AsRef<Path>, P2: AsRef<Path>>(
    build_path: P1,
    path: P2,
) -> Result<PathBuf> {
    let build_path_ref = build_path.as_ref();
    let path_ref = path.as_ref();
    let canonical_path_buf = path_ref.canonicalize().map_err(|err| {
        anyhow!("Failed to canonicalize absolute path: {:?}: {:?}", path_ref, err.to_string())
    })?;
    if canonical_path_buf.is_absolute() {
        diff_paths(&canonical_path_buf, &build_path).ok_or_else(|| {
            anyhow!(
                "Artifact path {:?} (from {:?}) cannot be formatted relative to build path {:?}",
                canonical_path_buf,
                path_ref,
                build_path_ref,
            )
        })
    } else {
        Err(anyhow!(
            "Canonicalized form of {:?} is {:?}, which is not an absolute path",
            path_ref,
            canonical_path_buf,
        ))
    }
}

#[cfg(test)]
mod tests {
    use {
        super::{ArtifactReader, FileArtifactReader},
        maplit::hashset,
        std::{
            fs::{create_dir, File},
            io::Write,
            path::Path,
        },
        tempfile::tempdir,
    };

    #[test]
    fn test_basic() {
        let dir = tempdir().unwrap().into_path();
        let mut loader = FileArtifactReader::new(&dir, &dir);
        let mut file = File::create(dir.join("foo")).unwrap();
        file.write_all(b"test_data").unwrap();
        file.sync_all().unwrap();
        let result = loader.read_bytes(&Path::new("foo"));
        assert_eq!(result.is_ok(), true);
        let data = result.unwrap();
        assert_eq!(data, b"test_data");
    }

    #[test]
    fn test_deps() {
        let build_path = tempdir().unwrap().into_path();
        let artifact_path_buf = build_path.join("artifacts");
        let artifact_path = artifact_path_buf.as_path();
        create_dir(&artifact_path).unwrap();
        let mut loader = FileArtifactReader::new(&build_path, artifact_path);

        let mut file = File::create(&artifact_path.join("foo")).unwrap();
        file.write_all(b"test_data").unwrap();
        file.sync_all().unwrap();

        let mut file = File::create(&artifact_path.join("bar")).unwrap();
        file.write_all(b"test_data").unwrap();
        file.sync_all().unwrap();

        assert_eq!(loader.read_bytes(&Path::new("foo")).is_ok(), true);
        assert_eq!(loader.read_bytes(&Path::new("bar")).is_ok(), true);
        assert_eq!(loader.read_bytes(&Path::new("foo")).is_ok(), true);
        let deps = loader.get_deps();
        assert_eq!(
            deps,
            hashset! {"artifacts/foo".to_string().into(), "artifacts/bar".to_string().into()}
        );
    }
}
