use crate::{bstr, bstr::BStr, Commit, ObjectDetached, Tree};

mod error {
    use crate::object;

    #[derive(Debug, thiserror::Error)]
    #[allow(missing_docs)]
    pub enum Error {
        #[error(transparent)]
        FindExistingObject(#[from] object::find::existing::Error),
        #[error("The commit could not be decoded fully or partially")]
        Decode(#[from] gix_object::decode::Error),
        #[error("Expected object of type {}, but got {}", .expected, .actual)]
        ObjectKind {
            expected: gix_object::Kind,
            actual: gix_object::Kind,
        },
    }
}

pub use error::Error;

/// Remove Lifetime
impl<'repo> Commit<'repo> {
    /// Create an owned instance of this object, copying our data in the process.
    pub fn detached(&self) -> ObjectDetached {
        ObjectDetached {
            id: self.id,
            kind: gix_object::Kind::Commit,
            data: self.data.clone(),
        }
    }

    /// Sever the connection to the `Repository` and turn this instance into a standalone object.
    pub fn detach(self) -> ObjectDetached {
        self.into()
    }

    /// Retrieve this instance's encoded data, leaving its own data empty.
    ///
    /// This method works around the immovability of members of this type.
    pub fn take_data(&mut self) -> Vec<u8> {
        std::mem::take(&mut self.data)
    }
}

impl<'repo> Commit<'repo> {
    /// Turn this objects id into a shortened id with a length in hex as configured by `core.abbrev`.
    pub fn short_id(&self) -> Result<gix_hash::Prefix, crate::id::shorten::Error> {
        use crate::ext::ObjectIdExt;
        self.id.attach(self.repo).shorten()
    }

    /// Parse the commits message into a [`MessageRef`][gix_object::commit::MessageRef]
    pub fn message(&self) -> Result<gix_object::commit::MessageRef<'_>, gix_object::decode::Error> {
        Ok(gix_object::commit::MessageRef::from_bytes(self.message_raw()?))
    }
    /// Decode the commit object until the message and return it.
    pub fn message_raw(&self) -> Result<&'_ BStr, gix_object::decode::Error> {
        gix_object::CommitRefIter::from_bytes(&self.data).message()
    }
    /// Obtain the message by using intricate knowledge about the encoding, which is fastest and
    /// can't fail at the expense of error handling.
    pub fn message_raw_sloppy(&self) -> &BStr {
        use bstr::ByteSlice;
        self.data
            .find(b"\n\n")
            .map(|pos| &self.data[pos + 2..])
            .unwrap_or_default()
            .as_bstr()
    }

    /// Decode the commit and obtain the time at which the commit was created.
    ///
    /// For the time at which it was authored, refer to `.decode()?.author.time`.
    pub fn time(&self) -> Result<gix_date::Time, Error> {
        Ok(self.committer()?.time)
    }

    /// Decode the entire commit object and return it for accessing all commit information.
    ///
    /// It will allocate only if there are more than 2 parents.
    ///
    /// Note that the returned commit object does make lookup easy and should be
    /// used for successive calls to string-ish information to avoid decoding the object
    /// more than once.
    pub fn decode(&self) -> Result<gix_object::CommitRef<'_>, gix_object::decode::Error> {
        gix_object::CommitRef::from_bytes(&self.data)
    }

    /// Return an iterator over tokens, representing this commit piece by piece.
    pub fn iter(&self) -> gix_object::CommitRefIter<'_> {
        gix_object::CommitRefIter::from_bytes(&self.data)
    }

    /// Return the commits author, with surrounding whitespace trimmed.
    pub fn author(&self) -> Result<gix_actor::SignatureRef<'_>, gix_object::decode::Error> {
        gix_object::CommitRefIter::from_bytes(&self.data)
            .author()
            .map(|s| s.trim())
    }

    /// Return the commits committer. with surrounding whitespace trimmed.
    pub fn committer(&self) -> Result<gix_actor::SignatureRef<'_>, gix_object::decode::Error> {
        gix_object::CommitRefIter::from_bytes(&self.data)
            .committer()
            .map(|s| s.trim())
    }

    /// Decode this commits parent ids on the fly without allocating.
    // TODO: tests
    pub fn parent_ids(&self) -> impl Iterator<Item = crate::Id<'repo>> + '_ {
        use crate::ext::ObjectIdExt;
        let repo = self.repo;
        gix_object::CommitRefIter::from_bytes(&self.data)
            .parent_ids()
            .map(move |id| id.attach(repo))
    }

    /// Parse the commit and return the tree object it points to.
    pub fn tree(&self) -> Result<Tree<'repo>, Error> {
        match self.tree_id()?.object()?.try_into_tree() {
            Ok(tree) => Ok(tree),
            Err(crate::object::try_into::Error { actual, expected, .. }) => Err(Error::ObjectKind { actual, expected }),
        }
    }

    /// Parse the commit and return the tree id it points to.
    pub fn tree_id(&self) -> Result<crate::Id<'repo>, gix_object::decode::Error> {
        gix_object::CommitRefIter::from_bytes(&self.data)
            .tree_id()
            .map(|id| crate::Id::from_id(id, self.repo))
    }

    /// Return our id own id with connection to this repository.
    pub fn id(&self) -> crate::Id<'repo> {
        use crate::ext::ObjectIdExt;
        self.id.attach(self.repo)
    }

    /// Obtain a platform for traversing ancestors of this commit.
    pub fn ancestors(&self) -> crate::revision::walk::Platform<'repo> {
        self.id().ancestors()
    }

    /// Create a platform to further configure a `git describe` operation to find a name for this commit by looking
    /// at the closest annotated tags (by default) in its past.
    #[cfg(feature = "revision")]
    pub fn describe(&self) -> crate::commit::describe::Platform<'repo> {
        crate::commit::describe::Platform {
            id: self.id,
            repo: self.repo,
            select: Default::default(),
            first_parent: false,
            id_as_fallback: false,
            max_candidates: 10,
        }
    }

    /// Extracts the PGP signature and the data that was used to create the signature, or `None` if it wasn't signed.
    // TODO: make it possible to verify the signature, probably by wrapping `SignedData`. It's quite some work to do it properly.
    pub fn signature(
        &self,
    ) -> Result<Option<(std::borrow::Cow<'_, BStr>, gix_object::commit::SignedData<'_>)>, gix_object::decode::Error>
    {
        gix_object::CommitRefIter::signature(&self.data)
    }
}

impl<'r> std::fmt::Debug for Commit<'r> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Commit({})", self.id)
    }
}
