//! The lockfile::public module represents a reasonable stable API for inspecting the contents of a lockfile which others can code against.

use std::collections::BTreeSet;
use std::fs::File;
use std::io::BufReader;
use std::path::Path;

use anyhow::Result;
use serde::Deserialize;

pub use crate::config::CrateId;
use crate::context::crate_context::{CrateDependency, Rule};
use crate::context::{CommonAttributes, Context};
use crate::select::Select;

/// Parse a lockfile at a path on disk.
pub fn parse(path: &Path) -> Result<impl CargoBazelLockfile> {
    let reader = BufReader::new(File::open(path)?);
    let lockfile: CargoBazelLockfileImpl = serde_json::from_reader(reader)?;
    Ok(lockfile)
}

/// CargoBazelLockfile provides a view over cargo-bazel's lockfile format,
/// providing information about the third-party dependencies of a workspace.
/// While the lockfile's format doesn't provide any kind of compatibility guarantees over time,
/// this type offers an interface which is likely to be publicly supportable.
/// No formal compatibility guarantees are offered around this type - it may change at any time,
/// but the maintainers will attempt to keep it as stable they reasonably can.
pub trait CargoBazelLockfile {
    /// Get the members of the local workspace.
    /// These are typically not very interesting on their own, but can be used as roots for navigating what dependencies these crates have.
    fn workspace_members(&self) -> BTreeSet<CrateId>;

    /// Get information about a specific crate (which may be in the local workspace, or an external dependency).
    fn crate_info(&self, crate_id: &CrateId) -> Option<CrateInfo>;
}

#[derive(Deserialize)]
#[serde(transparent)]
struct CargoBazelLockfileImpl(Context);

impl CargoBazelLockfile for CargoBazelLockfileImpl {
    fn workspace_members(&self) -> BTreeSet<CrateId> {
        self.0.workspace_members.keys().cloned().collect()
    }

    fn crate_info(&self, crate_id: &CrateId) -> Option<CrateInfo> {
        let crate_context = self.0.crates.get(crate_id)?;
        Some(CrateInfo {
            name: crate_context.name.clone(),
            version: crate_context.version.clone(),
            library_target_name: crate_context.library_target_name.clone(),
            is_proc_macro: crate_context
                .targets
                .iter()
                .any(|t| matches!(t, Rule::ProcMacro(_))),
            common_attributes: crate_context.common_attrs.clone(),
        })
    }
}

/// Information about a crate (which may be in-workspace or a dependency).
#[derive(Deserialize, PartialEq, Eq, Debug)]
pub struct CrateInfo {
    name: String,
    version: semver::Version,
    library_target_name: Option<String>,
    is_proc_macro: bool,

    common_attributes: CommonAttributes,
}

impl CrateInfo {
    /// The name of the crate.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// The version of the crate.
    pub fn version(&self) -> &semver::Version {
        &self.version
    }

    /// The name of the crate's root library target. This is the target that a dependent
    /// would get if they were to depend on this crate.
    pub fn library_target_name(&self) -> Option<&str> {
        self.library_target_name.as_deref()
    }

    /// Whether the crate is a procedural macro.
    pub fn is_proc_macro(&self) -> bool {
        self.is_proc_macro
    }

    /// Dependencies required to compile the crate, without procedural macro dependencies.
    pub fn normal_deps(&self) -> Select<BTreeSet<CrateDependency>> {
        self.common_attributes.deps.clone()
    }

    /// Dependencies required to compile the tests for the crate, but not needed to compile the crate itself, without procedural macro dependencies.
    pub fn dev_deps(&self) -> Select<BTreeSet<CrateDependency>> {
        self.common_attributes.deps_dev.clone()
    }

    /// Procedural macro dependencies required to compile the crate.
    pub fn proc_macro_deps(&self) -> Select<BTreeSet<CrateDependency>> {
        self.common_attributes.proc_macro_deps.clone()
    }

    /// Procedural macro dependencies required to compile the tests for the crate, but not needed to compile the crate itself.
    pub fn proc_macro_dev_deps(&self) -> Select<BTreeSet<CrateDependency>> {
        self.common_attributes.proc_macro_deps_dev.clone()
    }
}

#[cfg(test)]
mod test {
    use super::{parse, CargoBazelLockfile};
    use crate::config::CrateId;
    use crate::context::crate_context::CrateDependency;
    use semver::Version;
    use std::collections::BTreeSet;

    #[test]
    fn test() {
        let pkg_a = CrateId {
            name: String::from("pkg_a"),
            version: Version::new(0, 1, 0),
        };

        let want_workspace_member_names = {
            let mut set = BTreeSet::new();
            set.insert(pkg_a.clone());
            set.insert(CrateId {
                name: String::from("pkg_b"),
                version: Version::new(0, 1, 0),
            });
            set.insert(CrateId {
                name: String::from("pkg_c"),
                version: Version::new(0, 1, 0),
            });
            set
        };

        let runfiles = runfiles::Runfiles::create().unwrap();
        let path = runfiles
            .rlocation("rules_rust/crate_universe/test_data/cargo_bazel_lockfile/multi_package-cargo-bazel-lock.json");

        let parsed = parse(&path).unwrap();
        assert_eq!(parsed.workspace_members(), want_workspace_member_names);

        let got_pkg_a = parsed.crate_info(&pkg_a).unwrap();
        assert_eq!(got_pkg_a.name(), "pkg_a");
        assert_eq!(got_pkg_a.version(), &Version::new(0, 1, 0));
        assert_eq!(got_pkg_a.library_target_name(), Some("pkg_a"));
        assert!(!got_pkg_a.is_proc_macro());

        let serde_derive = CrateId {
            name: String::from("serde_derive"),
            version: Version::new(1, 0, 152),
        };
        let got_serde_derive = parsed.crate_info(&serde_derive).unwrap();
        assert_eq!(got_serde_derive.name(), "serde_derive");
        assert_eq!(got_serde_derive.version(), &Version::new(1, 0, 152));
        assert_eq!(got_serde_derive.library_target_name(), Some("serde_derive"));
        assert!(got_serde_derive.is_proc_macro);

        assert_eq!(
            got_pkg_a.normal_deps().values(),
            vec![
                CrateDependency {
                    id: CrateId {
                        name: String::from("anyhow"),
                        version: Version::new(1, 0, 69),
                    },
                    target: String::from("anyhow"),
                    alias: None,
                },
                CrateDependency {
                    id: CrateId {
                        name: String::from("reqwest"),
                        version: Version::new(0, 11, 14),
                    },
                    target: String::from("reqwest"),
                    alias: None,
                },
            ],
        );

        let async_process = CrateId {
            name: String::from("async-process"),
            version: Version::new(1, 6, 0),
        };
        let got_async_process = parsed.crate_info(&async_process).unwrap();
        let got_async_process_deps: BTreeSet<(Option<String>, String)> = got_async_process
            .normal_deps()
            .items()
            .into_iter()
            .map(|(config, dep)| (config, dep.id.name))
            .collect();
        assert_eq!(
            got_async_process_deps,
            vec![
                (None, "async-lock"),
                (None, "async-process"),
                (None, "cfg-if"),
                (None, "event-listener"),
                (None, "futures-lite"),
                (Some("cfg(unix)"), "async-io"),
                (Some("cfg(unix)"), "libc"),
                (Some("cfg(unix)"), "signal-hook"),
                (Some("cfg(windows)"), "blocking"),
                (Some("cfg(windows)"), "windows-sys"),
            ]
            .into_iter()
            .map(|(config, dep)| (config.map(String::from), String::from(dep)))
            .collect::<BTreeSet<_>>(),
        );
    }
}
