use log::{debug, trace};
use std::ffi::CString;
use std::io::Write;
use std::mem;
use std::path::Path;
use std::process::{Command, Stdio};
use std::ptr;
use url;

use crate::util::Binding;
use crate::{raw, Config, Error, IntoCString};

/// A structure to represent git credentials in libgit2.
pub struct Cred {
    raw: *mut raw::git_cred,
}

/// Management of the gitcredentials(7) interface.
pub struct CredentialHelper {
    /// A public field representing the currently discovered username from
    /// configuration.
    pub username: Option<String>,
    protocol: Option<String>,
    host: Option<String>,
    port: Option<u16>,
    path: Option<String>,
    url: String,
    commands: Vec<String>,
}

impl Cred {
    /// Create a "default" credential usable for Negotiate mechanisms like NTLM
    /// or Kerberos authentication.
    pub fn default() -> Result<Cred, Error> {
        crate::init();
        let mut out = ptr::null_mut();
        unsafe {
            try_call!(raw::git_cred_default_new(&mut out));
            Ok(Binding::from_raw(out))
        }
    }

    /// Create a new ssh key credential object used for querying an ssh-agent.
    ///
    /// The username specified is the username to authenticate.
    pub fn ssh_key_from_agent(username: &str) -> Result<Cred, Error> {
        crate::init();
        let mut out = ptr::null_mut();
        let username = CString::new(username)?;
        unsafe {
            try_call!(raw::git_cred_ssh_key_from_agent(&mut out, username));
            Ok(Binding::from_raw(out))
        }
    }

    /// Create a new passphrase-protected ssh key credential object.
    pub fn ssh_key(
        username: &str,
        publickey: Option<&Path>,
        privatekey: &Path,
        passphrase: Option<&str>,
    ) -> Result<Cred, Error> {
        crate::init();
        let username = CString::new(username)?;
        let publickey = crate::opt_cstr(publickey)?;
        let privatekey = privatekey.into_c_string()?;
        let passphrase = crate::opt_cstr(passphrase)?;
        let mut out = ptr::null_mut();
        unsafe {
            try_call!(raw::git_cred_ssh_key_new(
                &mut out, username, publickey, privatekey, passphrase
            ));
            Ok(Binding::from_raw(out))
        }
    }

    /// Create a new ssh key credential object reading the keys from memory.
    pub fn ssh_key_from_memory(
        username: &str,
        publickey: Option<&str>,
        privatekey: &str,
        passphrase: Option<&str>,
    ) -> Result<Cred, Error> {
        crate::init();
        let username = CString::new(username)?;
        let publickey = crate::opt_cstr(publickey)?;
        let privatekey = CString::new(privatekey)?;
        let passphrase = crate::opt_cstr(passphrase)?;
        let mut out = ptr::null_mut();
        unsafe {
            try_call!(raw::git_cred_ssh_key_memory_new(
                &mut out, username, publickey, privatekey, passphrase
            ));
            Ok(Binding::from_raw(out))
        }
    }

    /// Create a new plain-text username and password credential object.
    pub fn userpass_plaintext(username: &str, password: &str) -> Result<Cred, Error> {
        crate::init();
        let username = CString::new(username)?;
        let password = CString::new(password)?;
        let mut out = ptr::null_mut();
        unsafe {
            try_call!(raw::git_cred_userpass_plaintext_new(
                &mut out, username, password
            ));
            Ok(Binding::from_raw(out))
        }
    }

    /// Attempt to read `credential.helper` according to gitcredentials(7) [1]
    ///
    /// This function will attempt to parse the user's `credential.helper`
    /// configuration, invoke the necessary processes, and read off what the
    /// username/password should be for a particular url.
    ///
    /// The returned credential type will be a username/password credential if
    /// successful.
    ///
    /// [1]: https://www.kernel.org/pub/software/scm/git/docs/gitcredentials.html
    pub fn credential_helper(
        config: &Config,
        url: &str,
        username: Option<&str>,
    ) -> Result<Cred, Error> {
        match CredentialHelper::new(url)
            .config(config)
            .username(username)
            .execute()
        {
            Some((username, password)) => Cred::userpass_plaintext(&username, &password),
            None => Err(Error::from_str(
                "failed to acquire username/password \
                 from local configuration",
            )),
        }
    }

    /// Create a credential to specify a username.
    ///
    /// This is used with ssh authentication to query for the username if none is
    /// specified in the url.
    pub fn username(username: &str) -> Result<Cred, Error> {
        crate::init();
        let username = CString::new(username)?;
        let mut out = ptr::null_mut();
        unsafe {
            try_call!(raw::git_cred_username_new(&mut out, username));
            Ok(Binding::from_raw(out))
        }
    }

    /// Check whether a credential object contains username information.
    pub fn has_username(&self) -> bool {
        unsafe { raw::git_cred_has_username(self.raw) == 1 }
    }

    /// Return the type of credentials that this object represents.
    pub fn credtype(&self) -> raw::git_credtype_t {
        unsafe { (*self.raw).credtype }
    }

    /// Unwrap access to the underlying raw pointer, canceling the destructor
    pub unsafe fn unwrap(mut self) -> *mut raw::git_cred {
        mem::replace(&mut self.raw, ptr::null_mut())
    }
}

impl Binding for Cred {
    type Raw = *mut raw::git_cred;

    unsafe fn from_raw(raw: *mut raw::git_cred) -> Cred {
        Cred { raw }
    }
    fn raw(&self) -> *mut raw::git_cred {
        self.raw
    }
}

impl Drop for Cred {
    fn drop(&mut self) {
        if !self.raw.is_null() {
            unsafe {
                if let Some(f) = (*self.raw).free {
                    f(self.raw)
                }
            }
        }
    }
}

impl CredentialHelper {
    /// Create a new credential helper object which will be used to probe git's
    /// local credential configuration.
    ///
    /// The url specified is the namespace on which this will query credentials.
    /// Invalid urls are currently ignored.
    pub fn new(url: &str) -> CredentialHelper {
        let mut ret = CredentialHelper {
            protocol: None,
            host: None,
            port: None,
            path: None,
            username: None,
            url: url.to_string(),
            commands: Vec::new(),
        };

        // Parse out the (protocol, host) if one is available
        if let Ok(url) = url::Url::parse(url) {
            if let Some(url::Host::Domain(s)) = url.host() {
                ret.host = Some(s.to_string());
            }
            ret.port = url.port();
            ret.protocol = Some(url.scheme().to_string());
        }
        ret
    }

    /// Set the username that this credential helper will query with.
    ///
    /// By default the username is `None`.
    pub fn username(&mut self, username: Option<&str>) -> &mut CredentialHelper {
        self.username = username.map(|s| s.to_string());
        self
    }

    /// Query the specified configuration object to discover commands to
    /// execute, usernames to query, etc.
    pub fn config(&mut self, config: &Config) -> &mut CredentialHelper {
        // Figure out the configured username/helper program.
        //
        // see http://git-scm.com/docs/gitcredentials.html#_configuration_options
        if self.username.is_none() {
            self.config_username(config);
        }
        self.config_helper(config);
        self.config_use_http_path(config);
        self
    }

    // Configure the queried username from `config`
    fn config_username(&mut self, config: &Config) {
        let key = self.exact_key("username");
        self.username = config
            .get_string(&key)
            .ok()
            .or_else(|| {
                self.url_key("username")
                    .and_then(|s| config.get_string(&s).ok())
            })
            .or_else(|| config.get_string("credential.username").ok())
    }

    // Discover all `helper` directives from `config`
    fn config_helper(&mut self, config: &Config) {
        let exact = config.get_string(&self.exact_key("helper"));
        self.add_command(exact.as_ref().ok().map(|s| &s[..]));
        if let Some(key) = self.url_key("helper") {
            let url = config.get_string(&key);
            self.add_command(url.as_ref().ok().map(|s| &s[..]));
        }
        let global = config.get_string("credential.helper");
        self.add_command(global.as_ref().ok().map(|s| &s[..]));
    }

    // Discover `useHttpPath` from `config`
    fn config_use_http_path(&mut self, config: &Config) {
        let mut use_http_path = false;
        if let Some(value) = config.get_bool(&self.exact_key("useHttpPath")).ok() {
            use_http_path = value;
        } else if let Some(value) = self
            .url_key("useHttpPath")
            .and_then(|key| config.get_bool(&key).ok())
        {
            use_http_path = value;
        } else if let Some(value) = config.get_bool("credential.useHttpPath").ok() {
            use_http_path = value;
        }

        if use_http_path {
            if let Ok(url) = url::Url::parse(&self.url) {
                let path = url.path();
                // Url::parse always includes a leading slash for rooted URLs, while git does not.
                self.path = Some(path.strip_prefix('/').unwrap_or(path).to_string());
            }
        }
    }

    // Add a `helper` configured command to the list of commands to execute.
    //
    // see https://www.kernel.org/pub/software/scm/git/docs/technical
    //                           /api-credentials.html#_credential_helpers
    fn add_command(&mut self, cmd: Option<&str>) {
        let cmd = match cmd {
            Some("") | None => return,
            Some(s) => s,
        };

        if cmd.starts_with('!') {
            self.commands.push(cmd[1..].to_string());
        } else if cmd.contains("/") || cmd.contains("\\") {
            self.commands.push(cmd.to_string());
        } else {
            self.commands.push(format!("git credential-{}", cmd));
        }
    }

    fn exact_key(&self, name: &str) -> String {
        format!("credential.{}.{}", self.url, name)
    }

    fn url_key(&self, name: &str) -> Option<String> {
        match (&self.host, &self.protocol) {
            (&Some(ref host), &Some(ref protocol)) => {
                Some(format!("credential.{}://{}.{}", protocol, host, name))
            }
            _ => None,
        }
    }

    /// Execute this helper, attempting to discover a username/password pair.
    ///
    /// All I/O errors are ignored, (to match git behavior), and this function
    /// only succeeds if both a username and a password were found
    pub fn execute(&self) -> Option<(String, String)> {
        let mut username = self.username.clone();
        let mut password = None;
        for cmd in &self.commands {
            let (u, p) = self.execute_cmd(cmd, &username);
            if u.is_some() && username.is_none() {
                username = u;
            }
            if p.is_some() && password.is_none() {
                password = p;
            }
            if username.is_some() && password.is_some() {
                break;
            }
        }

        match (username, password) {
            (Some(u), Some(p)) => Some((u, p)),
            _ => None,
        }
    }

    // Execute the given `cmd`, providing the appropriate variables on stdin and
    // then afterwards parsing the output into the username/password on stdout.
    fn execute_cmd(
        &self,
        cmd: &str,
        username: &Option<String>,
    ) -> (Option<String>, Option<String>) {
        macro_rules! my_try( ($e:expr) => (
            match $e {
                Ok(e) => e,
                Err(e) => {
                    debug!("{} failed with {}", stringify!($e), e);
                    return (None, None)
                }
            }
        ) );

        // It looks like the `cmd` specification is typically bourne-shell-like
        // syntax, so try that first. If that fails, though, we may be on a
        // Windows machine for example where `sh` isn't actually available by
        // default. Most credential helper configurations though are pretty
        // simple (aka one or two space-separated strings) so also try to invoke
        // the process directly.
        //
        // If that fails then it's up to the user to put `sh` in path and make
        // sure it works.
        let mut c = Command::new("sh");
        c.arg("-c")
            .arg(&format!("{} get", cmd))
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped());
        debug!("executing credential helper {:?}", c);
        let mut p = match c.spawn() {
            Ok(p) => p,
            Err(e) => {
                debug!("`sh` failed to spawn: {}", e);
                let mut parts = cmd.split_whitespace();
                let mut c = Command::new(parts.next().unwrap());
                for arg in parts {
                    c.arg(arg);
                }
                c.arg("get")
                    .stdin(Stdio::piped())
                    .stdout(Stdio::piped())
                    .stderr(Stdio::piped());
                debug!("executing credential helper {:?}", c);
                match c.spawn() {
                    Ok(p) => p,
                    Err(e) => {
                        debug!("fallback of {:?} failed with {}", cmd, e);
                        return (None, None);
                    }
                }
            }
        };

        // Ignore write errors as the command may not actually be listening for
        // stdin
        {
            let stdin = p.stdin.as_mut().unwrap();
            if let Some(ref p) = self.protocol {
                let _ = writeln!(stdin, "protocol={}", p);
            }
            if let Some(ref p) = self.host {
                if let Some(ref p2) = self.port {
                    let _ = writeln!(stdin, "host={}:{}", p, p2);
                } else {
                    let _ = writeln!(stdin, "host={}", p);
                }
            }
            if let Some(ref p) = self.path {
                let _ = writeln!(stdin, "path={}", p);
            }
            if let Some(ref p) = *username {
                let _ = writeln!(stdin, "username={}", p);
            }
        }
        let output = my_try!(p.wait_with_output());
        if !output.status.success() {
            debug!(
                "credential helper failed: {}\nstdout ---\n{}\nstderr ---\n{}",
                output.status,
                String::from_utf8_lossy(&output.stdout),
                String::from_utf8_lossy(&output.stderr)
            );
            return (None, None);
        }
        trace!(
            "credential helper stderr ---\n{}",
            String::from_utf8_lossy(&output.stderr)
        );
        self.parse_output(output.stdout)
    }

    // Parse the output of a command into the username/password found
    fn parse_output(&self, output: Vec<u8>) -> (Option<String>, Option<String>) {
        // Parse the output of the command, looking for username/password
        let mut username = None;
        let mut password = None;
        for line in output.split(|t| *t == b'\n') {
            let mut parts = line.splitn(2, |t| *t == b'=');
            let key = parts.next().unwrap();
            let value = match parts.next() {
                Some(s) => s,
                None => {
                    trace!("ignoring output line: {}", String::from_utf8_lossy(line));
                    continue;
                }
            };
            let value = match String::from_utf8(value.to_vec()) {
                Ok(s) => s,
                Err(..) => continue,
            };
            match key {
                b"username" => username = Some(value),
                b"password" => password = Some(value),
                _ => {}
            }
        }
        (username, password)
    }
}

#[cfg(test)]
mod test {
    use std::env;
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::Path;
    use tempfile::TempDir;

    use crate::{Config, ConfigLevel, Cred, CredentialHelper};

    macro_rules! test_cfg( ($($k:expr => $v:expr),*) => ({
        let td = TempDir::new().unwrap();
        let mut cfg = Config::new().unwrap();
        cfg.add_file(&td.path().join("cfg"), ConfigLevel::Highest, false).unwrap();
        $(cfg.set_str($k, $v).unwrap();)*
        cfg
    }) );

    #[test]
    fn smoke() {
        Cred::default().unwrap();
    }

    #[test]
    fn credential_helper1() {
        let cfg = test_cfg! {
            "credential.helper" => "!f() { echo username=a; echo password=b; }; f"
        };
        let (u, p) = CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "a");
        assert_eq!(p, "b");
    }

    #[test]
    fn credential_helper2() {
        let cfg = test_cfg! {};
        assert!(CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .is_none());
    }

    #[test]
    fn credential_helper3() {
        let cfg = test_cfg! {
            "credential.https://example.com.helper" =>
                    "!f() { echo username=c; }; f",
            "credential.helper" => "!f() { echo username=a; echo password=b; }; f"
        };
        let (u, p) = CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "c");
        assert_eq!(p, "b");
    }

    #[test]
    fn credential_helper4() {
        if cfg!(windows) {
            return;
        } // shell scripts don't work on Windows

        let td = TempDir::new().unwrap();
        let path = td.path().join("script");
        File::create(&path)
            .unwrap()
            .write(
                br"\
#!/bin/sh
echo username=c
",
            )
            .unwrap();
        chmod(&path);
        let cfg = test_cfg! {
            "credential.https://example.com.helper" =>
                    &path.display().to_string()[..],
            "credential.helper" => "!f() { echo username=a; echo password=b; }; f"
        };
        let (u, p) = CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "c");
        assert_eq!(p, "b");
    }

    #[test]
    fn credential_helper5() {
        if cfg!(windows) {
            return;
        } // shell scripts don't work on Windows
        let td = TempDir::new().unwrap();
        let path = td.path().join("git-credential-script");
        File::create(&path)
            .unwrap()
            .write(
                br"\
#!/bin/sh
echo username=c
",
            )
            .unwrap();
        chmod(&path);

        let paths = env::var("PATH").unwrap();
        let paths =
            env::split_paths(&paths).chain(path.parent().map(|p| p.to_path_buf()).into_iter());
        env::set_var("PATH", &env::join_paths(paths).unwrap());

        let cfg = test_cfg! {
            "credential.https://example.com.helper" => "script",
            "credential.helper" => "!f() { echo username=a; echo password=b; }; f"
        };
        let (u, p) = CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "c");
        assert_eq!(p, "b");
    }

    #[test]
    fn credential_helper6() {
        let cfg = test_cfg! {
            "credential.helper" => ""
        };
        assert!(CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .is_none());
    }

    #[test]
    fn credential_helper7() {
        if cfg!(windows) {
            return;
        } // shell scripts don't work on Windows
        let td = TempDir::new().unwrap();
        let path = td.path().join("script");
        File::create(&path)
            .unwrap()
            .write(
                br"\
#!/bin/sh
echo username=$1
echo password=$2
",
            )
            .unwrap();
        chmod(&path);
        let cfg = test_cfg! {
            "credential.helper" => &format!("{} a b", path.display())
        };
        let (u, p) = CredentialHelper::new("https://example.com/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "a");
        assert_eq!(p, "b");
    }

    #[test]
    fn credential_helper8() {
        let cfg = test_cfg! {
            "credential.useHttpPath" => "true"
        };
        let mut helper = CredentialHelper::new("https://example.com/foo/bar");
        helper.config(&cfg);
        assert_eq!(helper.path.as_deref(), Some("foo/bar"));
    }

    #[test]
    fn credential_helper9() {
        let cfg = test_cfg! {
            "credential.helper" => "!f() { while read line; do eval $line; done; if [ \"$host\" = example.com:3000 ]; then echo username=a; echo password=b; fi; }; f"
        };
        let (u, p) = CredentialHelper::new("https://example.com:3000/foo/bar")
            .config(&cfg)
            .execute()
            .unwrap();
        assert_eq!(u, "a");
        assert_eq!(p, "b");
    }

    #[test]
    #[cfg(feature = "ssh")]
    fn ssh_key_from_memory() {
        let cred = Cred::ssh_key_from_memory(
            "test",
            Some("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDByAO8uj+kXicj6C2ODMspgmUoVyl5eaw8vR6a1yEnFuJFzevabNlN6Ut+CPT3TRnYk5BW73pyXBtnSL2X95BOnbjMDXc4YIkgs3YYHWnxbqsD4Pj/RoGqhf+gwhOBtL0poh8tT8WqXZYxdJQKLQC7oBqf3ykCEYulE4oeRUmNh4IzEE+skD/zDkaJ+S1HRD8D8YCiTO01qQnSmoDFdmIZTi8MS8Cw+O/Qhym1271ThMlhD6PubSYJXfE6rVbE7A9RzH73A6MmKBlzK8VTb4SlNSrr/DOk+L0uq+wPkv+pm+D9WtxoqQ9yl6FaK1cPawa3+7yRNle3m+72KCtyMkQv"),
            r#"
                -----BEGIN RSA PRIVATE KEY-----
                Proc-Type: 4,ENCRYPTED
                DEK-Info: AES-128-CBC,818C7722D3B01F2161C2ACF6A5BBAAE8

                3Cht4QB3PcoQ0I55j1B3m2ZzIC/mrh+K5nQeA1Vy2GBTMyM7yqGHqTOv7qLhJscd
                H+cB0Pm6yCr3lYuNrcKWOCUto+91P7ikyARruHVwyIxKdNx15uNulOzQJHQWNbA4
                RQHlhjON4atVo2FyJ6n+ujK6QiBg2PR5Vbbw/AtV6zBCFW3PhzDn+qqmHjpBFqj2
                vZUUe+MkDQcaF5J45XMHahhSdo/uKCDhfbylExp/+ACWkvxdPpsvcARM6X434ucD
                aPY+4i0/JyLkdbm0GFN9/q3i53qf4kCBhojFl4AYJdGI0AzAgbdTXZ7EJHbAGZHS
                os5K0oTwDVXMI0sSE2I/qHxaZZsDP1dOKq6di6SFPUp8liYimm7rNintRX88Gl2L
                g1ko9abp/NlgD0YY/3mad+NNAISDL/YfXq2fklH3En3/7ZrOVZFKfZXwQwas5g+p
                VQPKi3+ae74iOjLyuPDSc1ePmhUNYeP+9rLSc0wiaiHqls+2blPPDxAGMEo63kbz
                YPVjdmuVX4VWnyEsfTxxJdFDYGSNh6rlrrO1RFrex7kJvpg5gTX4M/FT8TfCd7Hn
                M6adXsLMqwu5tz8FuDmAtVdq8zdSrgZeAbpJ9D3EDOmZ70xz4XBL19ImxDp+Qqs2
                kQX7kobRzeeP2URfRoGr7XZikQWyQ2UASfPcQULY8R58QoZWWsQ4w51GZHg7TDnw
                1DRo/0OgkK7Gqf215nFmMpB4uyi58cq3WFwWQa1IqslkObpVgBQZcNZb/hKUYPGk
                g4zehfIgAfCdnQHwZvQ6Fdzhcs3SZeO+zVyuiZN3Gsi9HU0/1vpAKiuuOzcG02vF
                b6Y6hwsAA9yphF3atI+ARD4ZwXdDfzuGb3yJglMT3Fr/xuLwAvdchRo1spANKA0E
                tT5okLrK0H4wnHvf2SniVVWRhmJis0lQo9LjGGwRIdsPpVnJSDvaISIVF+fHT90r
                HvxN8zXI93x9jcPtwp7puQ1C7ehKJK10sZ71OLIZeuUgwt+5DRunqg6evPco9Go7
                UOGwcVhLY200KT+1k7zWzCS0yVQp2HRm6cxsZXAp4ClBSwIx15eIoLIrjZdJRjCq
                COp6pZx1fnvJ9ERIvl5hon+Ty+renMcFKz2HmchC7egpcqIxW9Dsv6zjhHle6pxb
                37GaEKHF2KA3RN+dSV/K8n+C9Yent5tx5Y9a/pMcgRGtgu+G+nyFmkPKn5Zt39yX
                qDpyM0LtbRVZPs+MgiqoGIwYc/ujoCq7GL38gezsBQoHaTt79yYBqCp6UR0LMuZ5
                f/7CtWqffgySfJ/0wjGidDAumDv8CK45AURpL/Z+tbFG3M9ar/LZz/Y6EyBcLtGY
                Wwb4zs8zXIA0qHrjNTnPqHDvezziArYfgPjxCIHMZzms9Yn8+N02p39uIytqg434
                BAlCqZ7GYdDFfTpWIwX+segTK9ux0KdBqcQv+9Fwwjkq9KySnRKqNl7ZJcefFZJq
                c6PA1iinZWBjuaO1HKx3PFulrl0bcpR9Kud1ZIyfnh5rwYN8UQkkcR/wZPla04TY
                8l5dq/LI/3G5sZXwUHKOcuQWTj7Saq7Q6gkKoMfqt0wC5bpZ1m17GHPoMz6GtX9O
                -----END RSA PRIVATE KEY-----
            "#,
            Some("test123"));
        assert!(cred.is_ok());
    }

    #[cfg(unix)]
    fn chmod(path: &Path) {
        use std::fs;
        use std::os::unix::prelude::*;
        let mut perms = fs::metadata(path).unwrap().permissions();
        perms.set_mode(0o755);
        fs::set_permissions(path, perms).unwrap();
    }
    #[cfg(windows)]
    fn chmod(_path: &Path) {}
}
