//! Utilities to handle program arguments and other values of interest.
use std::ffi::{OsStr, OsString};

use crate::bstr::{BString, ByteVec};

/// Returns the name of the agent for identification towards a remote server as statically known when compiling the crate.
/// Suitable for both `git` servers and HTTP servers, and used unless configured otherwise.
///
/// Note that it's meant to be used in conjunction with [`protocol::agent()`][crate::protocol::agent()] which
/// prepends `git/`.
pub fn agent() -> &'static str {
    concat!("oxide-", env!("CARGO_PKG_VERSION"))
}

/// Equivalent to `std::env::args_os()`, but with precomposed unicode on MacOS and other apple platforms.
/// It does not change the input arguments on any other platform.
///
/// Note that this ignores `core.precomposeUnicode` as git-config isn't available yet. It's default enabled in modern git though,
/// and generally decomposed unicode is nothing one would want in a git repository.
pub fn args_os() -> impl Iterator<Item = OsString> {
    args_os_opt(cfg!(target_vendor = "apple"))
}

/// Like [`args_os()`], but with the `precompose_unicode` parameter akin to `core.precomposeUnicode` in the Git configuration.
pub fn args_os_opt(precompose_unicode: bool) -> impl Iterator<Item = OsString> {
    std::env::args_os().map(move |arg| {
        if precompose_unicode {
            gix_utils::str::precompose_os_string(arg.into()).into_owned()
        } else {
            arg
        }
    })
}

/// Convert the given `input` into a `BString`, useful for usage in `clap`.
pub fn os_str_to_bstring(input: &OsStr) -> Option<BString> {
    Vec::from_os_string(input.into()).map(Into::into).ok()
}

/// Utilities to collate errors of common operations into one error type.
///
/// This is useful as this type can present an API to answer common questions, like whether a network request seems to have failed
/// spuriously or if the underlying repository seems to be corrupted.
/// Error collation supports all operations, including opening the repository.
///
/// ### Usage
///
/// The caller may define a function that specifies the result type as `Result<T, gix::env::collate::{operation}::Error>` to collect
/// errors into a well-known error type which provides an API for simple queries.
pub mod collate {

    ///
    #[allow(clippy::empty_docs)]
    pub mod fetch {
        /// An error which combines all possible errors when opening a repository, finding remotes and using them to fetch.
        ///
        /// It can be used to detect if the repository is likely be corrupted in some way, or if the fetch failed spuriously
        /// and thus can be retried.
        #[derive(Debug, thiserror::Error)]
        #[allow(missing_docs)]
        pub enum Error<E: std::error::Error + Send + Sync + 'static = std::convert::Infallible> {
            #[error(transparent)]
            Open(#[from] crate::open::Error),
            #[error(transparent)]
            FindExistingReference(#[from] crate::reference::find::existing::Error),
            #[error(transparent)]
            RemoteInit(#[from] crate::remote::init::Error),
            #[error(transparent)]
            FindExistingRemote(#[from] crate::remote::find::existing::Error),
            #[error(transparent)]
            #[cfg(feature = "credentials")]
            CredentialHelperConfig(#[from] crate::config::credential_helpers::Error),
            #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
            #[error(transparent)]
            Connect(#[from] crate::remote::connect::Error),
            #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
            #[error(transparent)]
            PrepareFetch(#[from] crate::remote::fetch::prepare::Error),
            #[cfg(any(feature = "blocking-network-client", feature = "async-network-client"))]
            #[error(transparent)]
            Fetch(#[from] crate::remote::fetch::Error),
            #[error(transparent)]
            Other(E),
        }

        #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
        impl<E> crate::protocol::transport::IsSpuriousError for Error<E>
        where
            E: std::error::Error + Send + Sync + 'static,
        {
            fn is_spurious(&self) -> bool {
                match self {
                    Error::Open(_)
                    | Error::CredentialHelperConfig(_)
                    | Error::RemoteInit(_)
                    | Error::FindExistingReference(_)
                    | Error::FindExistingRemote(_)
                    | Error::Other(_) => false,
                    Error::Connect(err) => err.is_spurious(),
                    Error::PrepareFetch(err) => err.is_spurious(),
                    Error::Fetch(err) => err.is_spurious(),
                }
            }
        }

        /// Queries
        impl<E> Error<E>
        where
            E: std::error::Error + Send + Sync + 'static,
        {
            /// Return true if repository corruption caused the failure.
            pub fn is_corrupted(&self) -> bool {
                match self {
                    Error::Open(crate::open::Error::NotARepository { .. } | crate::open::Error::Config(_)) => true,
                    #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
                    Error::PrepareFetch(crate::remote::fetch::prepare::Error::RefMap(
                        // Configuration couldn't be accessed or was incomplete.
                        crate::remote::ref_map::Error::GatherTransportConfig { .. }
                        | crate::remote::ref_map::Error::ConfigureCredentials(_),
                    )) => true,
                    // Maybe the value of the configuration was corrupted, or a file couldn't be removed.
                    #[cfg(any(feature = "async-network-client", feature = "blocking-network-client"))]
                    Error::Fetch(
                        crate::remote::fetch::Error::PackThreads(_)
                        | crate::remote::fetch::Error::PackIndexVersion(_)
                        | crate::remote::fetch::Error::RemovePackKeepFile { .. }
                        | crate::remote::fetch::Error::Negotiate(_),
                    ) => true,
                    _ => false,
                }
            }
        }
    }
}
