//! Blob operations.

use std::path::Path;

use crate::blob::types::{BlobContent, BlobInfo};
use crate::commit::types::CommitOid;
use crate::{GitDomain, GitError, GitResult};

impl GitDomain {
    pub fn blob_get(&self, oid: &CommitOid) -> GitResult<BlobInfo> {
        let oid = oid
            .to_oid()
            .map_err(|_| GitError::InvalidOid(oid.to_string()))?;

        let blob = self
            .repo()
            .find_blob(oid)
            .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?;

        Ok(BlobInfo::from_git2(&blob))
    }

    pub fn blob_exists(&self, oid: &CommitOid) -> bool {
        oid.to_oid()
            .ok()
            .and_then(|oid| self.repo.find_blob(oid).ok())
            .is_some()
    }

    pub fn blob_is_binary(&self, oid: &CommitOid) -> GitResult<bool> {
        let oid = oid
            .to_oid()
            .map_err(|_| GitError::InvalidOid(oid.to_string()))?;

        let blob = self
            .repo()
            .find_blob(oid)
            .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?;

        Ok(blob.is_binary())
    }

    pub fn blob_content(&self, oid: &CommitOid) -> GitResult<BlobContent> {
        let oid = oid
            .to_oid()
            .map_err(|_| GitError::InvalidOid(oid.to_string()))?;

        let blob = self
            .repo()
            .find_blob(oid)
            .map_err(|_| GitError::ObjectNotFound(oid.to_string()))?;

        Ok(BlobContent::from_git2(&blob))
    }

    pub fn blob_size(&self, oid: &CommitOid) -> GitResult<usize> {
        let info = self.blob_get(oid)?;
        Ok(info.size)
    }

    pub fn blob_create(&self, data: &[u8]) -> GitResult<CommitOid> {
        let oid = self
            .repo()
            .blob(data)
            .map_err(|e| GitError::Internal(e.to_string()))?;
        Ok(CommitOid::from_git2(oid))
    }

    pub fn blob_create_from_path(&self, path: &Path) -> GitResult<CommitOid> {
        let oid = self
            .repo()
            .blob_path(path)
            .map_err(|e| GitError::Internal(e.to_string()))?;
        Ok(CommitOid::from_git2(oid))
    }

    pub fn blob_create_from_string(&self, content: &str) -> GitResult<CommitOid> {
        self.blob_create(content.as_bytes())
    }
}
