use libc;
use raw::git_strarray;
use std::marker;
use std::mem;
use std::ops::Range;
use std::ptr;
use std::slice;
use std::str;
use std::{ffi::CString, os::raw::c_char};

use crate::string_array::StringArray;
use crate::util::Binding;
use crate::{raw, Buf, Direction, Error, FetchPrune, Oid, ProxyOptions, Refspec};
use crate::{AutotagOption, Progress, RemoteCallbacks, Repository};

/// A structure representing a [remote][1] of a git repository.
///
/// [1]: http://git-scm.com/book/en/Git-Basics-Working-with-Remotes
///
/// The lifetime is the lifetime of the repository that it is attached to. The
/// remote is used to manage fetches and pushes as well as refspecs.
pub struct Remote<'repo> {
    raw: *mut raw::git_remote,
    _marker: marker::PhantomData<&'repo Repository>,
}

/// An iterator over the refspecs that a remote contains.
pub struct Refspecs<'remote> {
    range: Range<usize>,
    remote: &'remote Remote<'remote>,
}

/// Description of a reference advertised by a remote server, given out on calls
/// to `list`.
pub struct RemoteHead<'remote> {
    raw: *const raw::git_remote_head,
    _marker: marker::PhantomData<&'remote str>,
}

/// Options which can be specified to various fetch operations.
pub struct FetchOptions<'cb> {
    callbacks: Option<RemoteCallbacks<'cb>>,
    proxy: Option<ProxyOptions<'cb>>,
    prune: FetchPrune,
    update_fetchhead: bool,
    download_tags: AutotagOption,
    follow_redirects: RemoteRedirect,
    custom_headers: Vec<CString>,
    custom_headers_ptrs: Vec<*const c_char>,
}

/// Options to control the behavior of a git push.
pub struct PushOptions<'cb> {
    callbacks: Option<RemoteCallbacks<'cb>>,
    proxy: Option<ProxyOptions<'cb>>,
    pb_parallelism: u32,
    follow_redirects: RemoteRedirect,
    custom_headers: Vec<CString>,
    custom_headers_ptrs: Vec<*const c_char>,
}

/// Holds callbacks for a connection to a `Remote`. Disconnects when dropped
pub struct RemoteConnection<'repo, 'connection, 'cb> {
    _callbacks: Box<RemoteCallbacks<'cb>>,
    _proxy: ProxyOptions<'cb>,
    remote: &'connection mut Remote<'repo>,
}

/// Remote redirection settings; whether redirects to another host are
/// permitted.
///
/// By default, git will follow a redirect on the initial request
/// (`/info/refs`), but not subsequent requests.
pub enum RemoteRedirect {
    /// Do not follow any off-site redirects at any stage of the fetch or push.
    None,
    /// Allow off-site redirects only upon the initial request. This is the
    /// default.
    Initial,
    /// Allow redirects at any stage in the fetch or push.
    All,
}

pub fn remote_into_raw(remote: Remote<'_>) -> *mut raw::git_remote {
    let ret = remote.raw;
    mem::forget(remote);
    ret
}

impl<'repo> Remote<'repo> {
    /// Ensure the remote name is well-formed.
    pub fn is_valid_name(remote_name: &str) -> bool {
        crate::init();
        let remote_name = CString::new(remote_name).unwrap();
        unsafe { raw::git_remote_is_valid_name(remote_name.as_ptr()) == 1 }
    }

    /// Create a detached remote
    ///
    /// Create a remote with the given url in-memory. You can use this
    /// when you have a URL instead of a remote's name.
    /// Contrasted with an anonymous remote, a detached remote will not
    /// consider any repo configuration values.
    pub fn create_detached<S: Into<Vec<u8>>>(url: S) -> Result<Remote<'repo>, Error> {
        crate::init();
        let mut ret = ptr::null_mut();
        let url = CString::new(url)?;
        unsafe {
            try_call!(raw::git_remote_create_detached(&mut ret, url));
            Ok(Binding::from_raw(ret))
        }
    }

    /// Get the remote's name.
    ///
    /// Returns `None` if this remote has not yet been named or if the name is
    /// not valid utf-8
    pub fn name(&self) -> Option<&str> {
        self.name_bytes().and_then(|s| str::from_utf8(s).ok())
    }

    /// Get the remote's name, in bytes.
    ///
    /// Returns `None` if this remote has not yet been named
    pub fn name_bytes(&self) -> Option<&[u8]> {
        unsafe { crate::opt_bytes(self, raw::git_remote_name(&*self.raw)) }
    }

    /// Get the remote's url.
    ///
    /// Returns `None` if the url is not valid utf-8
    pub fn url(&self) -> Option<&str> {
        str::from_utf8(self.url_bytes()).ok()
    }

    /// Get the remote's url as a byte array.
    pub fn url_bytes(&self) -> &[u8] {
        unsafe { crate::opt_bytes(self, raw::git_remote_url(&*self.raw)).unwrap() }
    }

    /// Get the remote's pushurl.
    ///
    /// Returns `None` if the pushurl is not valid utf-8
    pub fn pushurl(&self) -> Option<&str> {
        self.pushurl_bytes().and_then(|s| str::from_utf8(s).ok())
    }

    /// Get the remote's pushurl as a byte array.
    pub fn pushurl_bytes(&self) -> Option<&[u8]> {
        unsafe { crate::opt_bytes(self, raw::git_remote_pushurl(&*self.raw)) }
    }

    /// Get the remote's default branch.
    ///
    /// The remote (or more exactly its transport) must have connected to the
    /// remote repository. This default branch is available as soon as the
    /// connection to the remote is initiated and it remains available after
    /// disconnecting.
    pub fn default_branch(&self) -> Result<Buf, Error> {
        unsafe {
            let buf = Buf::new();
            try_call!(raw::git_remote_default_branch(buf.raw(), self.raw));
            Ok(buf)
        }
    }

    /// Open a connection to a remote.
    pub fn connect(&mut self, dir: Direction) -> Result<(), Error> {
        // TODO: can callbacks be exposed safely?
        unsafe {
            try_call!(raw::git_remote_connect(
                self.raw,
                dir,
                ptr::null(),
                ptr::null(),
                ptr::null()
            ));
        }
        Ok(())
    }

    /// Open a connection to a remote with callbacks and proxy settings
    ///
    /// Returns a `RemoteConnection` that will disconnect once dropped
    pub fn connect_auth<'connection, 'cb>(
        &'connection mut self,
        dir: Direction,
        cb: Option<RemoteCallbacks<'cb>>,
        proxy_options: Option<ProxyOptions<'cb>>,
    ) -> Result<RemoteConnection<'repo, 'connection, 'cb>, Error> {
        let cb = Box::new(cb.unwrap_or_else(RemoteCallbacks::new));
        let proxy_options = proxy_options.unwrap_or_else(ProxyOptions::new);
        unsafe {
            try_call!(raw::git_remote_connect(
                self.raw,
                dir,
                &cb.raw(),
                &proxy_options.raw(),
                ptr::null()
            ));
        }

        Ok(RemoteConnection {
            _callbacks: cb,
            _proxy: proxy_options,
            remote: self,
        })
    }

    /// Check whether the remote is connected
    pub fn connected(&mut self) -> bool {
        unsafe { raw::git_remote_connected(self.raw) == 1 }
    }

    /// Disconnect from the remote
    pub fn disconnect(&mut self) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_remote_disconnect(self.raw));
        }
        Ok(())
    }

    /// Download and index the packfile
    ///
    /// Connect to the remote if it hasn't been done yet, negotiate with the
    /// remote git which objects are missing, download and index the packfile.
    ///
    /// The .idx file will be created and both it and the packfile with be
    /// renamed to their final name.
    ///
    /// The `specs` argument is a list of refspecs to use for this negotiation
    /// and download. Use an empty array to use the base refspecs.
    pub fn download<Str: AsRef<str> + crate::IntoCString + Clone>(
        &mut self,
        specs: &[Str],
        opts: Option<&mut FetchOptions<'_>>,
    ) -> Result<(), Error> {
        let (_a, _b, arr) = crate::util::iter2cstrs(specs.iter())?;
        let raw = opts.map(|o| o.raw());
        unsafe {
            try_call!(raw::git_remote_download(self.raw, &arr, raw.as_ref()));
        }
        Ok(())
    }

    /// Cancel the operation
    ///
    /// At certain points in its operation, the network code checks whether the
    /// operation has been cancelled and if so stops the operation.
    pub fn stop(&mut self) -> Result<(), Error> {
        unsafe {
            try_call!(raw::git_remote_stop(self.raw));
        }
        Ok(())
    }

    /// Get the number of refspecs for a remote
    pub fn refspecs(&self) -> Refspecs<'_> {
        let cnt = unsafe { raw::git_remote_refspec_count(&*self.raw) as usize };
        Refspecs {
            range: 0..cnt,
            remote: self,
        }
    }

    /// Get the `nth` refspec from this remote.
    ///
    /// The `refspecs` iterator can be used to iterate over all refspecs.
    pub fn get_refspec(&self, i: usize) -> Option<Refspec<'repo>> {
        unsafe {
            let ptr = raw::git_remote_get_refspec(&*self.raw, i as libc::size_t);
            Binding::from_raw_opt(ptr)
        }
    }

    /// Download new data and update tips
    ///
    /// Convenience function to connect to a remote, download the data,
    /// disconnect and update the remote-tracking branches.
    ///
    /// # Examples
    ///
    /// Example of functionality similar to `git fetch origin/main`:
    ///
    /// ```no_run
    /// fn fetch_origin_main(repo: git2::Repository) -> Result<(), git2::Error> {
    ///     repo.find_remote("origin")?.fetch(&["main"], None, None)
    /// }
    ///
    /// let repo = git2::Repository::discover("rust").unwrap();
    /// fetch_origin_main(repo).unwrap();
    /// ```
    pub fn fetch<Str: AsRef<str> + crate::IntoCString + Clone>(
        &mut self,
        refspecs: &[Str],
        opts: Option<&mut FetchOptions<'_>>,
        reflog_msg: Option<&str>,
    ) -> Result<(), Error> {
        let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?;
        let msg = crate::opt_cstr(reflog_msg)?;
        let raw = opts.map(|o| o.raw());
        unsafe {
            try_call!(raw::git_remote_fetch(self.raw, &arr, raw.as_ref(), msg));
        }
        Ok(())
    }

    /// Update the tips to the new state
    pub fn update_tips(
        &mut self,
        callbacks: Option<&mut RemoteCallbacks<'_>>,
        update_fetchhead: bool,
        download_tags: AutotagOption,
        msg: Option<&str>,
    ) -> Result<(), Error> {
        let msg = crate::opt_cstr(msg)?;
        let cbs = callbacks.map(|cb| cb.raw());
        unsafe {
            try_call!(raw::git_remote_update_tips(
                self.raw,
                cbs.as_ref(),
                update_fetchhead,
                download_tags,
                msg
            ));
        }
        Ok(())
    }

    /// Perform a push
    ///
    /// Perform all the steps for a push. If no refspecs are passed then the
    /// configured refspecs will be used.
    ///
    /// Note that you'll likely want to use `RemoteCallbacks` and set
    /// `push_update_reference` to test whether all the references were pushed
    /// successfully.
    pub fn push<Str: AsRef<str> + crate::IntoCString + Clone>(
        &mut self,
        refspecs: &[Str],
        opts: Option<&mut PushOptions<'_>>,
    ) -> Result<(), Error> {
        let (_a, _b, arr) = crate::util::iter2cstrs(refspecs.iter())?;
        let raw = opts.map(|o| o.raw());
        unsafe {
            try_call!(raw::git_remote_push(self.raw, &arr, raw.as_ref()));
        }
        Ok(())
    }

    /// Get the statistics structure that is filled in by the fetch operation.
    pub fn stats(&self) -> Progress<'_> {
        unsafe { Binding::from_raw(raw::git_remote_stats(self.raw)) }
    }

    /// Get the remote repository's reference advertisement list.
    ///
    /// Get the list of references with which the server responds to a new
    /// connection.
    ///
    /// The remote (or more exactly its transport) must have connected to the
    /// remote repository. This list is available as soon as the connection to
    /// the remote is initiated and it remains available after disconnecting.
    pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> {
        let mut size = 0;
        let mut base = ptr::null_mut();
        unsafe {
            try_call!(raw::git_remote_ls(&mut base, &mut size, self.raw));
            assert_eq!(
                mem::size_of::<RemoteHead<'_>>(),
                mem::size_of::<*const raw::git_remote_head>()
            );
            let slice = slice::from_raw_parts(base as *const _, size as usize);
            Ok(mem::transmute::<
                &[*const raw::git_remote_head],
                &[RemoteHead<'_>],
            >(slice))
        }
    }

    /// Prune tracking refs that are no longer present on remote
    pub fn prune(&mut self, callbacks: Option<RemoteCallbacks<'_>>) -> Result<(), Error> {
        let cbs = Box::new(callbacks.unwrap_or_else(RemoteCallbacks::new));
        unsafe {
            try_call!(raw::git_remote_prune(self.raw, &cbs.raw()));
        }
        Ok(())
    }

    /// Get the remote's list of fetch refspecs
    pub fn fetch_refspecs(&self) -> Result<StringArray, Error> {
        unsafe {
            let mut raw: raw::git_strarray = mem::zeroed();
            try_call!(raw::git_remote_get_fetch_refspecs(&mut raw, self.raw));
            Ok(StringArray::from_raw(raw))
        }
    }

    /// Get the remote's list of push refspecs
    pub fn push_refspecs(&self) -> Result<StringArray, Error> {
        unsafe {
            let mut raw: raw::git_strarray = mem::zeroed();
            try_call!(raw::git_remote_get_push_refspecs(&mut raw, self.raw));
            Ok(StringArray::from_raw(raw))
        }
    }
}

impl<'repo> Clone for Remote<'repo> {
    fn clone(&self) -> Remote<'repo> {
        let mut ret = ptr::null_mut();
        let rc = unsafe { call!(raw::git_remote_dup(&mut ret, self.raw)) };
        assert_eq!(rc, 0);
        Remote {
            raw: ret,
            _marker: marker::PhantomData,
        }
    }
}

impl<'repo> Binding for Remote<'repo> {
    type Raw = *mut raw::git_remote;

    unsafe fn from_raw(raw: *mut raw::git_remote) -> Remote<'repo> {
        Remote {
            raw,
            _marker: marker::PhantomData,
        }
    }
    fn raw(&self) -> *mut raw::git_remote {
        self.raw
    }
}

impl<'repo> Drop for Remote<'repo> {
    fn drop(&mut self) {
        unsafe { raw::git_remote_free(self.raw) }
    }
}

impl<'repo> Iterator for Refspecs<'repo> {
    type Item = Refspec<'repo>;
    fn next(&mut self) -> Option<Refspec<'repo>> {
        self.range.next().and_then(|i| self.remote.get_refspec(i))
    }
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.range.size_hint()
    }
}
impl<'repo> DoubleEndedIterator for Refspecs<'repo> {
    fn next_back(&mut self) -> Option<Refspec<'repo>> {
        self.range
            .next_back()
            .and_then(|i| self.remote.get_refspec(i))
    }
}
impl<'repo> ExactSizeIterator for Refspecs<'repo> {}

#[allow(missing_docs)] // not documented in libgit2 :(
impl<'remote> RemoteHead<'remote> {
    /// Flag if this is available locally.
    pub fn is_local(&self) -> bool {
        unsafe { (*self.raw).local != 0 }
    }

    pub fn oid(&self) -> Oid {
        unsafe { Binding::from_raw(&(*self.raw).oid as *const _) }
    }
    pub fn loid(&self) -> Oid {
        unsafe { Binding::from_raw(&(*self.raw).loid as *const _) }
    }

    pub fn name(&self) -> &str {
        let b = unsafe { crate::opt_bytes(self, (*self.raw).name).unwrap() };
        str::from_utf8(b).unwrap()
    }

    pub fn symref_target(&self) -> Option<&str> {
        let b = unsafe { crate::opt_bytes(self, (*self.raw).symref_target) };
        b.map(|b| str::from_utf8(b).unwrap())
    }
}

impl<'cb> Default for FetchOptions<'cb> {
    fn default() -> Self {
        Self::new()
    }
}

impl<'cb> FetchOptions<'cb> {
    /// Creates a new blank set of fetch options
    pub fn new() -> FetchOptions<'cb> {
        FetchOptions {
            callbacks: None,
            proxy: None,
            prune: FetchPrune::Unspecified,
            update_fetchhead: true,
            download_tags: AutotagOption::Unspecified,
            follow_redirects: RemoteRedirect::Initial,
            custom_headers: Vec::new(),
            custom_headers_ptrs: Vec::new(),
        }
    }

    /// Set the callbacks to use for the fetch operation.
    pub fn remote_callbacks(&mut self, cbs: RemoteCallbacks<'cb>) -> &mut Self {
        self.callbacks = Some(cbs);
        self
    }

    /// Set the proxy options to use for the fetch operation.
    pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self {
        self.proxy = Some(opts);
        self
    }

    /// Set whether to perform a prune after the fetch.
    pub fn prune(&mut self, prune: FetchPrune) -> &mut Self {
        self.prune = prune;
        self
    }

    /// Set whether to write the results to FETCH_HEAD.
    ///
    /// Defaults to `true`.
    pub fn update_fetchhead(&mut self, update: bool) -> &mut Self {
        self.update_fetchhead = update;
        self
    }

    /// Set how to behave regarding tags on the remote, such as auto-downloading
    /// tags for objects we're downloading or downloading all of them.
    ///
    /// The default is to auto-follow tags.
    pub fn download_tags(&mut self, opt: AutotagOption) -> &mut Self {
        self.download_tags = opt;
        self
    }

    /// Set remote redirection settings; whether redirects to another host are
    /// permitted.
    ///
    /// By default, git will follow a redirect on the initial request
    /// (`/info/refs`), but not subsequent requests.
    pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self {
        self.follow_redirects = redirect;
        self
    }

    /// Set extra headers for this fetch operation.
    pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self {
        self.custom_headers = custom_headers
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect();
        self
    }
}

impl<'cb> Binding for FetchOptions<'cb> {
    type Raw = raw::git_fetch_options;

    unsafe fn from_raw(_raw: raw::git_fetch_options) -> FetchOptions<'cb> {
        panic!("unimplemented");
    }
    fn raw(&self) -> raw::git_fetch_options {
        raw::git_fetch_options {
            version: 1,
            callbacks: self
                .callbacks
                .as_ref()
                .map(|m| m.raw())
                .unwrap_or_else(|| RemoteCallbacks::new().raw()),
            proxy_opts: self
                .proxy
                .as_ref()
                .map(|m| m.raw())
                .unwrap_or_else(|| ProxyOptions::new().raw()),
            prune: crate::call::convert(&self.prune),
            update_fetchhead: crate::call::convert(&self.update_fetchhead),
            download_tags: crate::call::convert(&self.download_tags),
            follow_redirects: self.follow_redirects.raw(),
            custom_headers: git_strarray {
                count: self.custom_headers_ptrs.len(),
                strings: self.custom_headers_ptrs.as_ptr() as *mut _,
            },
        }
    }
}

impl<'cb> Default for PushOptions<'cb> {
    fn default() -> Self {
        Self::new()
    }
}

impl<'cb> PushOptions<'cb> {
    /// Creates a new blank set of push options
    pub fn new() -> PushOptions<'cb> {
        PushOptions {
            callbacks: None,
            proxy: None,
            pb_parallelism: 1,
            follow_redirects: RemoteRedirect::Initial,
            custom_headers: Vec::new(),
            custom_headers_ptrs: Vec::new(),
        }
    }

    /// Set the callbacks to use for the fetch operation.
    pub fn remote_callbacks(&mut self, cbs: RemoteCallbacks<'cb>) -> &mut Self {
        self.callbacks = Some(cbs);
        self
    }

    /// Set the proxy options to use for the fetch operation.
    pub fn proxy_options(&mut self, opts: ProxyOptions<'cb>) -> &mut Self {
        self.proxy = Some(opts);
        self
    }

    /// If the transport being used to push to the remote requires the creation
    /// of a pack file, this controls the number of worker threads used by the
    /// packbuilder when creating that pack file to be sent to the remote.
    ///
    /// if set to 0 the packbuilder will auto-detect the number of threads to
    /// create, and the default value is 1.
    pub fn packbuilder_parallelism(&mut self, parallel: u32) -> &mut Self {
        self.pb_parallelism = parallel;
        self
    }

    /// Set remote redirection settings; whether redirects to another host are
    /// permitted.
    ///
    /// By default, git will follow a redirect on the initial request
    /// (`/info/refs`), but not subsequent requests.
    pub fn follow_redirects(&mut self, redirect: RemoteRedirect) -> &mut Self {
        self.follow_redirects = redirect;
        self
    }

    /// Set extra headers for this push operation.
    pub fn custom_headers(&mut self, custom_headers: &[&str]) -> &mut Self {
        self.custom_headers = custom_headers
            .iter()
            .map(|&s| CString::new(s).unwrap())
            .collect();
        self.custom_headers_ptrs = self.custom_headers.iter().map(|s| s.as_ptr()).collect();
        self
    }
}

impl<'cb> Binding for PushOptions<'cb> {
    type Raw = raw::git_push_options;

    unsafe fn from_raw(_raw: raw::git_push_options) -> PushOptions<'cb> {
        panic!("unimplemented");
    }
    fn raw(&self) -> raw::git_push_options {
        raw::git_push_options {
            version: 1,
            callbacks: self
                .callbacks
                .as_ref()
                .map(|m| m.raw())
                .unwrap_or_else(|| RemoteCallbacks::new().raw()),
            proxy_opts: self
                .proxy
                .as_ref()
                .map(|m| m.raw())
                .unwrap_or_else(|| ProxyOptions::new().raw()),
            pb_parallelism: self.pb_parallelism as libc::c_uint,
            follow_redirects: self.follow_redirects.raw(),
            custom_headers: git_strarray {
                count: self.custom_headers_ptrs.len(),
                strings: self.custom_headers_ptrs.as_ptr() as *mut _,
            },
        }
    }
}

impl<'repo, 'connection, 'cb> RemoteConnection<'repo, 'connection, 'cb> {
    /// Check whether the remote is (still) connected
    pub fn connected(&mut self) -> bool {
        self.remote.connected()
    }

    /// Get the remote repository's reference advertisement list.
    ///
    /// This list is available as soon as the connection to
    /// the remote is initiated and it remains available after disconnecting.
    pub fn list(&self) -> Result<&[RemoteHead<'_>], Error> {
        self.remote.list()
    }

    /// Get the remote's default branch.
    ///
    /// This default branch is available as soon as the connection to the remote
    /// is initiated and it remains available after disconnecting.
    pub fn default_branch(&self) -> Result<Buf, Error> {
        self.remote.default_branch()
    }

    /// access remote bound to this connection
    pub fn remote(&mut self) -> &mut Remote<'repo> {
        self.remote
    }
}

impl<'repo, 'connection, 'cb> Drop for RemoteConnection<'repo, 'connection, 'cb> {
    fn drop(&mut self) {
        drop(self.remote.disconnect());
    }
}

impl Default for RemoteRedirect {
    fn default() -> Self {
        RemoteRedirect::Initial
    }
}

impl RemoteRedirect {
    fn raw(&self) -> raw::git_remote_redirect_t {
        match self {
            RemoteRedirect::None => raw::GIT_REMOTE_REDIRECT_NONE,
            RemoteRedirect::Initial => raw::GIT_REMOTE_REDIRECT_INITIAL,
            RemoteRedirect::All => raw::GIT_REMOTE_REDIRECT_ALL,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::{AutotagOption, PushOptions};
    use crate::{Direction, FetchOptions, Remote, RemoteCallbacks, Repository};
    use std::cell::Cell;
    use tempfile::TempDir;

    #[test]
    fn smoke() {
        let (td, repo) = crate::test::repo_init();
        t!(repo.remote("origin", "/path/to/nowhere"));
        drop(repo);

        let repo = t!(Repository::init(td.path()));
        let mut origin = t!(repo.find_remote("origin"));
        assert_eq!(origin.name(), Some("origin"));
        assert_eq!(origin.url(), Some("/path/to/nowhere"));
        assert_eq!(origin.pushurl(), None);

        t!(repo.remote_set_url("origin", "/path/to/elsewhere"));
        t!(repo.remote_set_pushurl("origin", Some("/path/to/elsewhere")));

        let stats = origin.stats();
        assert_eq!(stats.total_objects(), 0);

        t!(origin.stop());
    }

    #[test]
    fn create_remote() {
        let td = TempDir::new().unwrap();
        let remote = td.path().join("remote");
        Repository::init_bare(&remote).unwrap();

        let (_td, repo) = crate::test::repo_init();
        let url = if cfg!(unix) {
            format!("file://{}", remote.display())
        } else {
            format!(
                "file:///{}",
                remote.display().to_string().replace("\\", "/")
            )
        };

        let mut origin = repo.remote("origin", &url).unwrap();
        assert_eq!(origin.name(), Some("origin"));
        assert_eq!(origin.url(), Some(&url[..]));
        assert_eq!(origin.pushurl(), None);

        {
            let mut specs = origin.refspecs();
            let spec = specs.next().unwrap();
            assert!(specs.next().is_none());
            assert_eq!(spec.str(), Some("+refs/heads/*:refs/remotes/origin/*"));
            assert_eq!(spec.dst(), Some("refs/remotes/origin/*"));
            assert_eq!(spec.src(), Some("refs/heads/*"));
            assert!(spec.is_force());
        }
        assert!(origin.refspecs().next_back().is_some());
        {
            let remotes = repo.remotes().unwrap();
            assert_eq!(remotes.len(), 1);
            assert_eq!(remotes.get(0), Some("origin"));
            assert_eq!(remotes.iter().count(), 1);
            assert_eq!(remotes.iter().next().unwrap(), Some("origin"));
        }

        origin.connect(Direction::Push).unwrap();
        assert!(origin.connected());
        origin.disconnect().unwrap();

        origin.connect(Direction::Fetch).unwrap();
        assert!(origin.connected());
        origin.download(&[] as &[&str], None).unwrap();
        origin.disconnect().unwrap();

        {
            let mut connection = origin.connect_auth(Direction::Push, None, None).unwrap();
            assert!(connection.connected());
        }
        assert!(!origin.connected());

        {
            let mut connection = origin.connect_auth(Direction::Fetch, None, None).unwrap();
            assert!(connection.connected());
        }
        assert!(!origin.connected());

        origin.fetch(&[] as &[&str], None, None).unwrap();
        origin.fetch(&[] as &[&str], None, Some("foo")).unwrap();
        origin
            .update_tips(None, true, AutotagOption::Unspecified, None)
            .unwrap();
        origin
            .update_tips(None, true, AutotagOption::All, Some("foo"))
            .unwrap();

        t!(repo.remote_add_fetch("origin", "foo"));
        t!(repo.remote_add_fetch("origin", "bar"));
    }

    #[test]
    fn rename_remote() {
        let (_td, repo) = crate::test::repo_init();
        repo.remote("origin", "foo").unwrap();
        drop(repo.remote_rename("origin", "foo"));
        drop(repo.remote_delete("foo"));
    }

    #[test]
    fn create_remote_anonymous() {
        let td = TempDir::new().unwrap();
        let repo = Repository::init(td.path()).unwrap();

        let origin = repo.remote_anonymous("/path/to/nowhere").unwrap();
        assert_eq!(origin.name(), None);
        drop(origin.clone());
    }

    #[test]
    fn is_valid() {
        assert!(Remote::is_valid_name("foobar"));
        assert!(!Remote::is_valid_name("\x01"));
    }

    #[test]
    fn transfer_cb() {
        let (td, _repo) = crate::test::repo_init();
        let td2 = TempDir::new().unwrap();
        let url = crate::test::path2url(&td.path());

        let repo = Repository::init(td2.path()).unwrap();
        let progress_hit = Cell::new(false);
        {
            let mut callbacks = RemoteCallbacks::new();
            let mut origin = repo.remote("origin", &url).unwrap();

            callbacks.transfer_progress(|_progress| {
                progress_hit.set(true);
                true
            });
            origin
                .fetch(
                    &[] as &[&str],
                    Some(FetchOptions::new().remote_callbacks(callbacks)),
                    None,
                )
                .unwrap();

            let list = t!(origin.list());
            assert_eq!(list.len(), 2);
            assert_eq!(list[0].name(), "HEAD");
            assert!(!list[0].is_local());
            assert_eq!(list[1].name(), "refs/heads/main");
            assert!(!list[1].is_local());
        }
        assert!(progress_hit.get());
    }

    /// This test is meant to assure that the callbacks provided to connect will not cause
    /// segfaults
    #[test]
    fn connect_list() {
        let (td, _repo) = crate::test::repo_init();
        let td2 = TempDir::new().unwrap();
        let url = crate::test::path2url(&td.path());

        let repo = Repository::init(td2.path()).unwrap();
        let mut callbacks = RemoteCallbacks::new();
        callbacks.sideband_progress(|_progress| {
            // no-op
            true
        });

        let mut origin = repo.remote("origin", &url).unwrap();

        {
            let mut connection = origin
                .connect_auth(Direction::Fetch, Some(callbacks), None)
                .unwrap();
            assert!(connection.connected());

            let list = t!(connection.list());
            assert_eq!(list.len(), 2);
            assert_eq!(list[0].name(), "HEAD");
            assert!(!list[0].is_local());
            assert_eq!(list[1].name(), "refs/heads/main");
            assert!(!list[1].is_local());
        }
        assert!(!origin.connected());
    }

    #[test]
    fn push() {
        let (_td, repo) = crate::test::repo_init();
        let td2 = TempDir::new().unwrap();
        let td3 = TempDir::new().unwrap();
        let url = crate::test::path2url(&td2.path());

        let mut opts = crate::RepositoryInitOptions::new();
        opts.bare(true);
        opts.initial_head("main");
        Repository::init_opts(td2.path(), &opts).unwrap();
        // git push
        let mut remote = repo.remote("origin", &url).unwrap();
        let mut updated = false;
        {
            let mut callbacks = RemoteCallbacks::new();
            callbacks.push_update_reference(|refname, status| {
                updated = true;
                assert_eq!(refname, "refs/heads/main");
                assert_eq!(status, None);
                Ok(())
            });
            let mut options = PushOptions::new();
            options.remote_callbacks(callbacks);
            remote
                .push(&["refs/heads/main"], Some(&mut options))
                .unwrap();
        }
        assert!(updated);

        let repo = Repository::clone(&url, td3.path()).unwrap();
        let commit = repo.head().unwrap().target().unwrap();
        let commit = repo.find_commit(commit).unwrap();
        assert_eq!(commit.message(), Some("initial\n\nbody"));
    }

    #[test]
    fn prune() {
        let (td, remote_repo) = crate::test::repo_init();
        let oid = remote_repo.head().unwrap().target().unwrap();
        let commit = remote_repo.find_commit(oid).unwrap();
        remote_repo.branch("stale", &commit, true).unwrap();

        let td2 = TempDir::new().unwrap();
        let url = crate::test::path2url(&td.path());
        let repo = Repository::clone(&url, &td2).unwrap();

        fn assert_branch_count(repo: &Repository, count: usize) {
            assert_eq!(
                repo.branches(Some(crate::BranchType::Remote))
                    .unwrap()
                    .filter(|b| b.as_ref().unwrap().0.name().unwrap() == Some("origin/stale"))
                    .count(),
                count,
            );
        }

        assert_branch_count(&repo, 1);

        // delete `stale` branch on remote repo
        let mut stale_branch = remote_repo
            .find_branch("stale", crate::BranchType::Local)
            .unwrap();
        stale_branch.delete().unwrap();

        // prune
        let mut remote = repo.find_remote("origin").unwrap();
        remote.connect(Direction::Push).unwrap();
        let mut callbacks = RemoteCallbacks::new();
        callbacks.update_tips(|refname, _a, b| {
            assert_eq!(refname, "refs/remotes/origin/stale");
            assert!(b.is_zero());
            true
        });
        remote.prune(Some(callbacks)).unwrap();
        assert_branch_count(&repo, 0);
    }
}
