//! Crate specific information embedded into [crate::context::Context] objects.

use std::collections::{BTreeMap, BTreeSet};

use cargo_metadata::{Node, Package, PackageId};
use serde::{Deserialize, Serialize};

use crate::config::CrateId;
use crate::metadata::{CrateAnnotation, Dependency, PairredExtras, SourceAnnotation};
use crate::utils::sanitize_module_name;
use crate::utils::starlark::{Glob, SelectList, SelectMap, SelectStringDict, SelectStringList};

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
pub struct CrateDependency {
    /// The [CrateId] of the dependency
    pub id: CrateId,

    /// The target name of the dependency. Note this may differ from the
    /// dependency's package name in cases such as build scripts.
    pub target: String,

    /// Some dependencies are assigned aliases. This is tracked here
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub alias: Option<String>,
}

#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct TargetAttributes {
    /// The module name of the crate (notably, not the package name).
    pub crate_name: String,

    /// The path to the crate's root source file, relative to the manifest.
    pub crate_root: Option<String>,

    /// A glob pattern of all source files required by the target
    pub srcs: Glob,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
pub enum Rule {
    /// `cargo_build_script`
    BuildScript(TargetAttributes),

    /// `rust_proc_macro`
    ProcMacro(TargetAttributes),

    /// `rust_library`
    Library(TargetAttributes),

    /// `rust_binary`
    Binary(TargetAttributes),
}

/// A set of attributes common to most `rust_library`, `rust_proc_macro`, and other
/// [core rules of `rules_rust`](https://bazelbuild.github.io/rules_rust/defs.html).
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct CommonAttributes {
    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub compile_data: SelectStringList,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub compile_data_glob: BTreeSet<String>,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub crate_features: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub data: SelectStringList,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub data_glob: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub deps: SelectList<CrateDependency>,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub extra_deps: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub deps_dev: SelectList<CrateDependency>,

    pub edition: String,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub linker_script: Option<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub proc_macro_deps: SelectList<CrateDependency>,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub extra_proc_macro_deps: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub proc_macro_deps_dev: SelectList<CrateDependency>,

    #[serde(skip_serializing_if = "SelectStringDict::should_skip_serializing")]
    pub rustc_env: SelectStringDict,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub rustc_env_files: SelectStringList,

    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub rustc_flags: Vec<String>,

    pub version: String,

    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub tags: Vec<String>,
}

impl Default for CommonAttributes {
    fn default() -> Self {
        Self {
            compile_data: Default::default(),
            // Generated targets include all files in their package by default
            compile_data_glob: BTreeSet::from(["**".to_owned()]),
            crate_features: Default::default(),
            data: Default::default(),
            data_glob: Default::default(),
            deps: Default::default(),
            extra_deps: Default::default(),
            deps_dev: Default::default(),
            edition: Default::default(),
            linker_script: Default::default(),
            proc_macro_deps: Default::default(),
            extra_proc_macro_deps: Default::default(),
            proc_macro_deps_dev: Default::default(),
            rustc_env: Default::default(),
            rustc_env_files: Default::default(),
            rustc_flags: Default::default(),
            version: Default::default(),
            tags: Default::default(),
        }
    }
}

// Build script attributes. See
// https://bazelbuild.github.io/rules_rust/cargo.html#cargo_build_script
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct BuildScriptAttributes {
    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub compile_data: SelectStringList,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub data: SelectStringList,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub data_glob: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub deps: SelectList<CrateDependency>,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub extra_deps: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectStringDict::should_skip_serializing")]
    pub build_script_env: SelectStringDict,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub extra_proc_macro_deps: BTreeSet<String>,

    #[serde(skip_serializing_if = "SelectList::should_skip_serializing")]
    pub proc_macro_deps: SelectList<CrateDependency>,

    #[serde(skip_serializing_if = "SelectStringDict::should_skip_serializing")]
    pub rustc_env: SelectStringDict,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub rustc_flags: SelectStringList,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub rustc_env_files: SelectStringList,

    #[serde(skip_serializing_if = "SelectStringList::should_skip_serializing")]
    pub tools: SelectStringList,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub links: Option<String>,

    #[serde(skip_serializing_if = "BTreeSet::is_empty")]
    pub toolchains: BTreeSet<String>,
}

impl Default for BuildScriptAttributes {
    fn default() -> Self {
        Self {
            compile_data: Default::default(),
            data: Default::default(),
            // Build scripts include all sources by default
            data_glob: BTreeSet::from(["**".to_owned()]),
            deps: Default::default(),
            extra_deps: Default::default(),
            build_script_env: Default::default(),
            extra_proc_macro_deps: Default::default(),
            proc_macro_deps: Default::default(),
            rustc_env: Default::default(),
            rustc_flags: Default::default(),
            rustc_env_files: Default::default(),
            tools: Default::default(),
            links: Default::default(),
            toolchains: Default::default(),
        }
    }
}

#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Clone)]
#[serde(default)]
pub struct CrateContext {
    /// The package name of the current crate
    pub name: String,

    /// The full version of the current crate
    pub version: String,

    /// Optional source annotations if they were discoverable in the
    /// lockfile. Workspace Members will not have source annotations and
    /// potentially others.
    pub repository: Option<SourceAnnotation>,

    /// A list of all targets (lib, proc-macro, bin) associated with this package
    pub targets: Vec<Rule>,

    /// The name of the crate's root library target. This is the target that a dependent
    /// would get if they were to depend on `{crate_name}`.
    pub library_target_name: Option<String>,

    /// A set of attributes common to most [Rule] types or target types.
    pub common_attrs: CommonAttributes,

    /// Optional attributes for build scripts. This field is only populated if
    /// a build script (`custom-build`) target is defined for the crate.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub build_script_attrs: Option<BuildScriptAttributes>,

    /// The license used by the crate
    pub license: Option<String>,

    /// Additional text to add to the generated BUILD file.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub additive_build_file_content: Option<String>,
}

impl CrateContext {
    pub fn new(
        annotation: &CrateAnnotation,
        packages: &BTreeMap<PackageId, Package>,
        source_annotations: &BTreeMap<PackageId, SourceAnnotation>,
        extras: &BTreeMap<CrateId, PairredExtras>,
        include_build_scripts: bool,
    ) -> Self {
        let package: &Package = &packages[&annotation.node.id];
        let current_crate_id = CrateId::new(package.name.clone(), package.version.to_string());

        let new_crate_dep = |dep: Dependency| -> CrateDependency {
            let pkg = &packages[&dep.package_id];

            // Unfortunately, The package graph and resolve graph of cargo metadata have different representations
            // for the crate names (resolve graph sanitizes names to match module names) so to get the rest of this
            // content to align when rendering, the dependency target needs to be explicitly sanitized.
            let target = sanitize_module_name(&dep.target_name);

            CrateDependency {
                id: CrateId::new(pkg.name.clone(), pkg.version.to_string()),
                target,
                alias: dep.alias,
            }
        };

        // Convert the dependencies into renderable strings
        let deps = annotation.deps.normal_deps.clone().map(new_crate_dep);
        let deps_dev = annotation.deps.normal_dev_deps.clone().map(new_crate_dep);
        let proc_macro_deps = annotation.deps.proc_macro_deps.clone().map(new_crate_dep);
        let proc_macro_deps_dev = annotation
            .deps
            .proc_macro_dev_deps
            .clone()
            .map(new_crate_dep);

        // Gather all "common" attributes
        let mut common_attrs = CommonAttributes {
            crate_features: annotation.node.features.iter().cloned().collect(),
            deps,
            deps_dev,
            edition: package.edition.clone(),
            proc_macro_deps,
            proc_macro_deps_dev,
            version: package.version.to_string(),
            ..Default::default()
        };

        let include_build_scripts =
            Self::crate_includes_build_script(package, extras, include_build_scripts);

        // Iterate over each target and produce a Bazel target for all supported "kinds"
        let targets = Self::collect_targets(&annotation.node, packages, include_build_scripts);

        // Parse the library crate name from the set of included targets
        let library_target_name = {
            let lib_targets: Vec<&TargetAttributes> = targets
                .iter()
                .filter_map(|t| match t {
                    Rule::ProcMacro(attrs) => Some(attrs),
                    Rule::Library(attrs) => Some(attrs),
                    _ => None,
                })
                .collect();

            // TODO: There should only be at most 1 library target. This case
            // should be handled in a more intelligent way.
            assert!(lib_targets.len() <= 1);
            lib_targets
                .iter()
                .last()
                .map(|attr| attr.crate_name.clone())
        };

        // Gather any build-script related attributes
        let build_script_target = targets.iter().find_map(|r| match r {
            Rule::BuildScript(attr) => Some(attr),
            _ => None,
        });

        let build_script_attrs = if let Some(target) = build_script_target {
            // Track the build script dependency
            common_attrs.deps.insert(
                CrateDependency {
                    id: current_crate_id,
                    target: target.crate_name.clone(),
                    alias: None,
                },
                None,
            );

            let build_deps = annotation.deps.build_deps.clone().map(new_crate_dep);
            let build_proc_macro_deps = annotation
                .deps
                .build_proc_macro_deps
                .clone()
                .map(new_crate_dep);

            Some(BuildScriptAttributes {
                deps: build_deps,
                proc_macro_deps: build_proc_macro_deps,
                links: package.links.clone(),
                ..Default::default()
            })
        } else {
            None
        };

        // Save the repository information for the current crate
        let repository = source_annotations.get(&package.id).cloned();

        // Identify the license type
        let license = package.license.clone();

        // Create the crate's context and apply extra settings
        CrateContext {
            name: package.name.clone(),
            version: package.version.to_string(),
            repository,
            targets,
            library_target_name,
            common_attrs,
            build_script_attrs,
            license,
            additive_build_file_content: None,
        }
        .with_overrides(extras)
    }

    fn with_overrides(mut self, extras: &BTreeMap<CrateId, PairredExtras>) -> Self {
        let id = CrateId::new(self.name.clone(), self.version.clone());

        // Insert all overrides/extras
        if let Some(pairred_override) = extras.get(&id) {
            let crate_extra = &pairred_override.crate_extra;

            // Deps
            if let Some(extra) = &crate_extra.deps {
                self.common_attrs.extra_deps = extra.clone();
            }

            // Proc macro deps
            if let Some(extra) = &crate_extra.proc_macro_deps {
                self.common_attrs.extra_proc_macro_deps = extra.clone();
            }

            // Compile data
            if let Some(extra) = &crate_extra.compile_data {
                for data in extra.iter() {
                    self.common_attrs.compile_data.insert(data.clone(), None);
                }
            }

            // Compile data glob
            if let Some(extra) = &crate_extra.compile_data_glob {
                self.common_attrs.compile_data_glob.extend(extra.clone());
            }

            // Crate features
            if let Some(extra) = &crate_extra.crate_features {
                for data in extra.iter() {
                    self.common_attrs.crate_features.insert(data.clone());
                }
            }

            // Data
            if let Some(extra) = &crate_extra.data {
                for data in extra.iter() {
                    self.common_attrs.data.insert(data.clone(), None);
                }
            }

            // Data glob
            if let Some(extra) = &crate_extra.data_glob {
                self.common_attrs.data_glob.extend(extra.clone());
            }

            // Rustc flags
            if let Some(extra) = &crate_extra.rustc_flags {
                self.common_attrs.rustc_flags.append(&mut extra.clone());
            }

            // Rustc env
            if let Some(extra) = &crate_extra.rustc_env {
                self.common_attrs.rustc_env.insert(extra.clone(), None);
            }

            // Rustc env files
            if let Some(extra) = &crate_extra.rustc_env_files {
                for data in extra.iter() {
                    self.common_attrs.rustc_env_files.insert(data.clone(), None);
                }
            }

            // Build script Attributes
            if let Some(attrs) = &mut self.build_script_attrs {
                // Deps
                if let Some(extra) = &crate_extra.build_script_deps {
                    attrs.extra_deps = extra.clone();
                }

                // Proc macro deps
                if let Some(extra) = &crate_extra.build_script_proc_macro_deps {
                    attrs.extra_proc_macro_deps = extra.clone();
                }

                // Data
                if let Some(extra) = &crate_extra.build_script_data {
                    for data in extra {
                        attrs.data.insert(data.clone(), None);
                    }
                }

                // Tools
                if let Some(extra) = &crate_extra.build_script_tools {
                    for data in extra {
                        attrs.tools.insert(data.clone(), None);
                    }
                }

                // Toolchains
                if let Some(extra) = &crate_extra.build_script_toolchains {
                    for data in extra {
                        attrs.toolchains.insert(data.clone());
                    }
                }

                // Data glob
                if let Some(extra) = &crate_extra.build_script_data_glob {
                    attrs.data_glob.extend(extra.clone());
                }

                // Rustc env
                if let Some(extra) = &crate_extra.build_script_rustc_env {
                    attrs.rustc_env.insert(extra.clone(), None);
                }

                // Build script env
                if let Some(extra) = &crate_extra.build_script_env {
                    attrs.build_script_env.insert(extra.clone(), None);
                }
            }

            // Extra build contents
            self.additive_build_file_content = crate_extra
                .additive_build_file_content
                .as_ref()
                .map(|content| {
                    // For prettier rendering, dedent the build contents
                    textwrap::dedent(content)
                });

            // Git shallow_since
            if let Some(SourceAnnotation::Git { shallow_since, .. }) = &mut self.repository {
                *shallow_since = crate_extra.shallow_since.clone()
            }

            // Patch attributes
            if let Some(repository) = &mut self.repository {
                match repository {
                    SourceAnnotation::Git {
                        patch_args,
                        patch_tool,
                        patches,
                        ..
                    } => {
                        *patch_args = crate_extra.patch_args.clone();
                        *patch_tool = crate_extra.patch_tool.clone();
                        *patches = crate_extra.patches.clone();
                    }
                    SourceAnnotation::Http {
                        patch_args,
                        patch_tool,
                        patches,
                        ..
                    } => {
                        *patch_args = crate_extra.patch_args.clone();
                        *patch_tool = crate_extra.patch_tool.clone();
                        *patches = crate_extra.patches.clone();
                    }
                }
            }
        }

        self
    }

    /// Determine whether or not a crate __should__ include a build script
    /// (build.rs) if it happens to have one.
    fn crate_includes_build_script(
        package: &Package,
        overrides: &BTreeMap<CrateId, PairredExtras>,
        default_generate_build_script: bool,
    ) -> bool {
        // Locate extra settings for the current package.
        let settings = overrides
            .iter()
            .find(|(_, settings)| settings.package_id == package.id);

        // If the crate has extra settings, which explicitly set `gen_build_script`, always use
        // this value, otherwise, fallback to the provided default.
        settings
            .and_then(|(_, settings)| settings.crate_extra.gen_build_script)
            .unwrap_or(default_generate_build_script)
    }

    /// Collect all Bazel targets that should be generated for a particular Package
    fn collect_targets(
        node: &Node,
        packages: &BTreeMap<PackageId, Package>,
        include_build_scripts: bool,
    ) -> Vec<Rule> {
        let package = &packages[&node.id];

        let package_root = package
            .manifest_path
            .as_std_path()
            .parent()
            .expect("Every manifest should have a parent directory");

        package
            .targets
            .iter()
            .flat_map(|target| {
                target
                    .kind
                    .iter()
                    .filter_map(|kind| {
                        // Unfortunately, The package graph and resolve graph of cargo metadata have different representations
                        // for the crate names (resolve graph sanitizes names to match module names) so to get the rest of this
                        // content to align when rendering, the package target names are always sanitized.
                        let crate_name = sanitize_module_name(&target.name);

                        // Locate the crate's root source file relative to the package root normalized for unix
                        let crate_root = pathdiff::diff_paths(&target.src_path, package_root).map(
                            // Normalize the path so that it always renders the same regardless of platform
                            |root| root.to_string_lossy().replace('\\', "/"),
                        );

                        // Conditionally check to see if the dependencies is a build-script target
                        if include_build_scripts && kind == "custom-build" {
                            return Some(Rule::BuildScript(TargetAttributes {
                                crate_name,
                                crate_root,
                                srcs: Glob::new_rust_srcs(),
                            }));
                        }

                        // Check to see if the dependencies is a proc-macro target
                        if kind == "proc-macro" {
                            return Some(Rule::ProcMacro(TargetAttributes {
                                crate_name,
                                crate_root,
                                srcs: Glob::new_rust_srcs(),
                            }));
                        }

                        // Check to see if the dependencies is a library target
                        if ["lib", "rlib"].contains(&kind.as_str()) {
                            return Some(Rule::Library(TargetAttributes {
                                crate_name,
                                crate_root,
                                srcs: Glob::new_rust_srcs(),
                            }));
                        }

                        // Check to see if the dependencies is a library target
                        if kind == "bin" {
                            return Some(Rule::Binary(TargetAttributes {
                                crate_name: target.name.clone(),
                                crate_root,
                                srcs: Glob::new_rust_srcs(),
                            }));
                        }

                        None
                    })
                    .collect::<Vec<Rule>>()
            })
            .collect()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    use crate::config::CrateAnnotations;
    use crate::metadata::Annotations;

    fn common_annotations() -> Annotations {
        Annotations::new(
            crate::test::metadata::common(),
            crate::test::lockfile::common(),
            crate::config::Config::default(),
        )
        .unwrap()
    }

    #[test]
    fn new_context() {
        let annotations = common_annotations();

        let crate_annotation = &annotations.metadata.crates[&PackageId {
            repr: "common 0.1.0 (path+file://{TEMP_DIR}/common)".to_owned(),
        }];

        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            false,
        );

        assert_eq!(context.name, "common");
        assert_eq!(
            context.targets,
            vec![
                Rule::Library(TargetAttributes {
                    crate_name: "common".to_owned(),
                    crate_root: Some("lib.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                }),
                Rule::Binary(TargetAttributes {
                    crate_name: "common-bin".to_owned(),
                    crate_root: Some("main.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                }),
            ]
        );
    }

    #[test]
    fn context_with_overrides() {
        let annotations = common_annotations();

        let package_id = PackageId {
            repr: "common 0.1.0 (path+file://{TEMP_DIR}/common)".to_owned(),
        };

        let crate_annotation = &annotations.metadata.crates[&package_id];

        let mut pairred_extras = BTreeMap::new();
        pairred_extras.insert(
            CrateId::new("common".to_owned(), "0.1.0".to_owned()),
            PairredExtras {
                package_id,
                crate_extra: CrateAnnotations {
                    data_glob: Some(BTreeSet::from(["**/data_glob/**".to_owned()])),
                    ..CrateAnnotations::default()
                },
            },
        );

        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &pairred_extras,
            false,
        );

        assert_eq!(context.name, "common");
        assert_eq!(
            context.targets,
            vec![
                Rule::Library(TargetAttributes {
                    crate_name: "common".to_owned(),
                    crate_root: Some("lib.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                }),
                Rule::Binary(TargetAttributes {
                    crate_name: "common-bin".to_owned(),
                    crate_root: Some("main.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                }),
            ]
        );
        assert_eq!(
            context.common_attrs.data_glob,
            BTreeSet::from(["**/data_glob/**".to_owned()])
        );
    }

    fn build_script_annotations() -> Annotations {
        Annotations::new(
            crate::test::metadata::build_scripts(),
            crate::test::lockfile::build_scripts(),
            crate::config::Config::default(),
        )
        .unwrap()
    }

    fn crate_type_annotations() -> Annotations {
        Annotations::new(
            crate::test::metadata::crate_types(),
            crate::test::lockfile::crate_types(),
            crate::config::Config::default(),
        )
        .unwrap()
    }

    #[test]
    fn context_with_build_script() {
        let annotations = build_script_annotations();

        let package_id = PackageId {
            repr: "openssl-sys 0.9.72 (registry+https://github.com/rust-lang/crates.io-index)"
                .to_owned(),
        };

        let crate_annotation = &annotations.metadata.crates[&package_id];

        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            true,
        );

        assert_eq!(context.name, "openssl-sys");
        assert!(context.build_script_attrs.is_some());
        assert_eq!(
            context.targets,
            vec![
                Rule::Library(TargetAttributes {
                    crate_name: "openssl_sys".to_owned(),
                    crate_root: Some("src/lib.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                }),
                Rule::BuildScript(TargetAttributes {
                    crate_name: "build_script_main".to_owned(),
                    crate_root: Some("build/main.rs".to_owned()),
                    srcs: Glob::new_rust_srcs(),
                })
            ]
        );

        // Cargo build scripts should include all sources
        assert!(context.build_script_attrs.unwrap().data_glob.contains("**"));
    }

    #[test]
    fn context_disabled_build_script() {
        let annotations = build_script_annotations();

        let package_id = PackageId {
            repr: "openssl-sys 0.9.72 (registry+https://github.com/rust-lang/crates.io-index)"
                .to_owned(),
        };

        let crate_annotation = &annotations.metadata.crates[&package_id];

        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            false,
        );

        assert_eq!(context.name, "openssl-sys");
        assert!(context.build_script_attrs.is_none());
        assert_eq!(
            context.targets,
            vec![Rule::Library(TargetAttributes {
                crate_name: "openssl_sys".to_owned(),
                crate_root: Some("src/lib.rs".to_owned()),
                srcs: Glob::new_rust_srcs(),
            })],
        );
    }

    #[test]
    fn context_rlib_crate_type() {
        let annotations = crate_type_annotations();

        let package_id = PackageId {
            repr: "sysinfo 0.22.5 (registry+https://github.com/rust-lang/crates.io-index)"
                .to_owned(),
        };

        let crate_annotation = &annotations.metadata.crates[&package_id];

        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            false,
        );

        assert_eq!(context.name, "sysinfo");
        assert!(context.build_script_attrs.is_none());
        assert_eq!(
            context.targets,
            vec![Rule::Library(TargetAttributes {
                crate_name: "sysinfo".to_owned(),
                crate_root: Some("src/lib.rs".to_owned()),
                srcs: Glob::new_rust_srcs(),
            })],
        );
    }
}
