//! 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::{AliasRule, CrateId, GenBinaries};
use crate::metadata::{CrateAnnotation, Dependency, PairedExtras, SourceAnnotation};
use crate::select::Select;
use crate::utils::sanitize_module_name;
use crate::utils::starlark::{Glob, Label};

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
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(crate) struct TargetAttributes {
    /// The module name of the crate (notably, not the package name).
    //
    // This must be the first field of `TargetAttributes` to make it the
    // lexicographically first thing the derived `Ord` implementation will sort
    // by. The `Ord` impl controls the order of multiple rules of the same type
    // in the same BUILD file. In particular, this makes packages with multiple
    // bin crates generate those `rust_binary` targets in alphanumeric order.
    pub(crate) crate_name: String,

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

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

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

    /// `rust_proc_macro`
    ProcMacro(TargetAttributes),

    /// `rust_binary`
    Binary(TargetAttributes),

    /// `cargo_build_script`
    BuildScript(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, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub(crate) struct CommonAttributes {
    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) compile_data: Select<BTreeSet<Label>>,

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

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) data: Select<BTreeSet<Label>>,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) deps: Select<BTreeSet<CrateDependency>>,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) deps_dev: Select<BTreeSet<CrateDependency>>,

    pub(crate) edition: String,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) proc_macro_deps: Select<BTreeSet<CrateDependency>>,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) proc_macro_deps_dev: Select<BTreeSet<CrateDependency>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) rustc_env: Select<BTreeMap<String, String>>,

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

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

    pub(crate) version: String,

    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub(crate) 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, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub(crate) struct BuildScriptAttributes {
    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) compile_data: Select<BTreeSet<Label>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) data: Select<BTreeSet<Label>>,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) deps: Select<BTreeSet<CrateDependency>>,

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

    // TODO: refactor a crate with a build.rs file from two into three bazel
    // rules in order to deduplicate link_dep information. Currently as the
    // crate depends upon the build.rs file, the build.rs cannot find the
    // information for the normal dependencies of the crate. This could be
    // solved by switching the dependency graph from:
    //
    //   rust_library -> cargo_build_script
    //
    // to:
    //
    //   rust_library ->-+-->------------------->--+
    //                   |                         |
    //                   +--> cargo_build_script --+--> crate dependencies
    //
    // in which either all of the deps are in crate dependencies, or just the
    // normal dependencies. This could be handled a special rule, or just using
    // a `filegroup`.
    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) link_deps: Select<BTreeSet<CrateDependency>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) extra_link_deps: Select<BTreeSet<Label>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) build_script_env: Select<BTreeMap<String, String>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) rundir: Select<String>,

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) proc_macro_deps: Select<BTreeSet<CrateDependency>>,

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) rustc_env: Select<BTreeMap<String, String>>,

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

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

    #[serde(skip_serializing_if = "Select::is_empty")]
    pub(crate) tools: Select<BTreeSet<Label>>,

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

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

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(),
            link_deps: Default::default(),
            extra_link_deps: Default::default(),
            build_script_env: Default::default(),
            rundir: 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, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub(crate) struct CrateContext {
    /// The package name of the current crate
    pub(crate) name: String,

    /// The full version of the current crate
    pub(crate) version: semver::Version,

    /// The package URL of the current crate
    #[serde(default)]
    pub(crate) package_url: Option<String>,

    /// Optional source annotations if they were discoverable in the
    /// lockfile. Workspace Members will not have source annotations and
    /// potentially others.
    #[serde(default)]
    pub(crate) repository: Option<SourceAnnotation>,

    /// A list of all targets (lib, proc-macro, bin) associated with this package
    #[serde(default)]
    pub(crate) targets: BTreeSet<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}`.
    #[serde(default)]
    pub(crate) library_target_name: Option<String>,

    /// A set of attributes common to most [Rule] types or target types.
    #[serde(default)]
    pub(crate) 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")]
    #[serde(default)]
    pub(crate) build_script_attrs: Option<BuildScriptAttributes>,

    /// The license used by the crate
    #[serde(default)]
    pub(crate) license: Option<String>,

    /// The SPDX licence IDs
    /// #[serde(default)]
    pub(crate) license_ids: BTreeSet<String>,

    /// The license file
    #[serde(default)]
    pub(crate) license_file: Option<String>,

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

    /// If true, disables pipelining for library targets generated for this crate
    #[serde(skip_serializing_if = "std::ops::Not::not")]
    #[serde(default)]
    pub(crate) disable_pipelining: bool,

    /// Extra targets that should be aliased.
    #[serde(skip_serializing_if = "BTreeMap::is_empty")]
    #[serde(default)]
    pub(crate) extra_aliased_targets: BTreeMap<String, String>,

    /// Transition rule to use instead of `alias`.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[serde(default)]
    pub(crate) alias_rule: Option<AliasRule>,
}

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

        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.clone()),
                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: crate_features
                .get(&current_crate_id)
                .cloned()
                .unwrap_or_default(),

            deps,
            deps_dev,
            edition: package.edition.as_str().to_string(),
            proc_macro_deps,
            proc_macro_deps_dev,
            version: package.version.to_string(),
            ..Default::default()
        };

        // Locate extra settings for the current package.
        let package_extra = extras
            .iter()
            .find(|(_, settings)| settings.package_id == package.id);

        let include_build_scripts =
            Self::crate_includes_build_script(package_extra, include_build_scripts);

        let gen_none = GenBinaries::Some(BTreeSet::new());
        let gen_binaries = package_extra
            .and_then(|(_, settings)| settings.crate_extra.gen_binaries.as_ref())
            .unwrap_or(if include_binaries {
                &GenBinaries::All
            } else {
                &gen_none
            });

        // Iterate over each target and produce a Bazel target for all supported "kinds"
        let targets = Self::collect_targets(
            &annotation.node,
            packages,
            gen_binaries,
            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_link_deps = annotation.deps.build_link_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,
                link_deps: build_link_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 mut license_ids: BTreeSet<String> = BTreeSet::new();
        if let Some(license) = &package.license {
            if let Ok(parse_result) = spdx::Expression::parse_mode(license, spdx::ParseMode::LAX) {
                parse_result.requirements().for_each(|er| {
                    if let Some(license_id) = er.req.license.id() {
                        license_ids.insert(license_id.name.to_string());
                    }
                });
            }
        }

        let license_file = Self::locate_license_file(package);

        let package_url: Option<String> = match package.repository {
            Some(..) => package.repository.clone(),
            None => package.homepage.clone(),
        };

        // Create the crate's context and apply extra settings
        CrateContext {
            name: package.name.clone(),
            version: package.version.clone(),
            license: package.license.clone(),
            license_ids,
            license_file,
            package_url,
            repository,
            targets,
            library_target_name,
            common_attrs,
            build_script_attrs,
            additive_build_file_content: None,
            disable_pipelining: false,
            extra_aliased_targets: BTreeMap::new(),
            alias_rule: None,
        }
        .with_overrides(extras)
    }

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

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

            // Deps
            if let Some(extra) = &crate_extra.deps {
                self.common_attrs.extra_deps =
                    Select::merge(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 =
                    Select::merge(self.common_attrs.extra_proc_macro_deps, extra.clone());
            }

            // Compile data
            if let Some(extra) = &crate_extra.compile_data {
                self.common_attrs.compile_data =
                    Select::merge(self.common_attrs.compile_data, extra.clone());
            }

            // 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 {
                self.common_attrs.crate_features =
                    Select::merge(self.common_attrs.crate_features, extra.clone());
            }

            // Data
            if let Some(extra) = &crate_extra.data {
                self.common_attrs.data = Select::merge(self.common_attrs.data, extra.clone());
            }

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

            // Disable pipelining
            if crate_extra.disable_pipelining {
                self.disable_pipelining = true;
            }

            // Rustc flags
            if let Some(extra) = &crate_extra.rustc_flags {
                self.common_attrs.rustc_flags =
                    Select::merge(self.common_attrs.rustc_flags, extra.clone());
            }

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

            // Rustc env files
            if let Some(extra) = &crate_extra.rustc_env_files {
                self.common_attrs.rustc_env_files =
                    Select::merge(self.common_attrs.rustc_env_files, extra.clone());
            }

            // 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 = Select::merge(attrs.extra_deps.clone(), extra.clone());
                }

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

                // Data
                if let Some(extra) = &crate_extra.build_script_data {
                    attrs.data = Select::merge(attrs.data.clone(), extra.clone());
                }

                // Tools
                if let Some(extra) = &crate_extra.build_script_tools {
                    attrs.tools = Select::merge(attrs.tools.clone(), extra.clone());
                }

                // Toolchains
                if let Some(extra) = &crate_extra.build_script_toolchains {
                    attrs.toolchains.extend(extra.iter().cloned());
                }

                // 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 = Select::merge(attrs.rustc_env.clone(), extra.clone());
                }

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

                if let Some(rundir) = &crate_extra.build_script_rundir {
                    attrs.rundir = Select::merge(attrs.rundir.clone(), rundir.clone());
                }
            }

            // 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)
                });

            // Extra aliased targets
            if let Some(extra) = &crate_extra.extra_aliased_targets {
                self.extra_aliased_targets.append(&mut extra.clone());
            }

            // Transition alias
            if let Some(alias_rule) = &crate_extra.alias_rule {
                self.alias_rule.get_or_insert(alias_rule.clone());
            }

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

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

        self
    }

    fn locate_license_file(package: &Package) -> Option<String> {
        if let Some(license_file_path) = &package.license_file {
            return Some(license_file_path.to_string());
        }
        let package_root = package
            .manifest_path
            .as_std_path()
            .parent()
            .expect("Every manifest should have a parent directory");
        if package_root.exists() {
            let mut paths: Vec<_> = package_root
                .read_dir()
                .unwrap()
                .map(|r| r.unwrap())
                .collect();
            paths.sort_by_key(|dir| dir.path());
            for path in paths {
                if let Some(file_name) = path.file_name().to_str() {
                    if file_name.to_uppercase().starts_with("LICENSE") {
                        return Some(file_name.to_string());
                    }
                }
            }
        }
        None
    }

    /// 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_extra: Option<(&CrateId, &PairedExtras)>,
        default_generate_build_script: bool,
    ) -> bool {
        // If the crate has extra settings, which explicitly set `gen_build_script`, always use
        // this value, otherwise, fallback to the provided default.
        package_extra
            .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>,
        gen_binaries: &GenBinaries,
        include_build_scripts: bool,
    ) -> BTreeSet<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(move |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 if the target kind is binary and is one of the ones included in gen_binaries
                    if kind == "bin"
                        && match gen_binaries {
                            GenBinaries::All => true,
                            GenBinaries::Some(set) => set.contains(&target.name),
                        }
                    {
                        return Some(Rule::Binary(TargetAttributes {
                            crate_name: target.name.clone(),
                            crate_root,
                            srcs: Glob::new_rust_srcs(),
                        }));
                    }

                    None
                })
            })
            .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 include_binaries = false;
        let include_build_scripts = false;
        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            &annotations.crate_features,
            include_binaries,
            include_build_scripts,
        );

        assert_eq!(context.name, "common");
        assert_eq!(
            context.targets,
            BTreeSet::from([Rule::Library(TargetAttributes {
                crate_name: "common".to_owned(),
                crate_root: Some("lib.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(), semver::Version::new(0, 1, 0)),
            PairedExtras {
                package_id,
                crate_extra: CrateAnnotations {
                    gen_binaries: Some(GenBinaries::All),
                    data_glob: Some(BTreeSet::from(["**/data_glob/**".to_owned()])),
                    ..CrateAnnotations::default()
                },
            },
        );

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

        assert_eq!(context.name, "common");
        assert_eq!(
            context.targets,
            BTreeSet::from([
                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.87 (registry+https://github.com/rust-lang/crates.io-index)"
                .to_owned(),
        };

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

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

        assert_eq!(context.name, "openssl-sys");
        assert!(context.build_script_attrs.is_some());
        assert_eq!(
            context.targets,
            BTreeSet::from([
                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.87 (registry+https://github.com/rust-lang/crates.io-index)"
                .to_owned(),
        };

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

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

        assert_eq!(context.name, "openssl-sys");
        assert!(context.build_script_attrs.is_none());
        assert_eq!(
            context.targets,
            BTreeSet::from([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 include_binaries = false;
        let include_build_scripts = false;
        let context = CrateContext::new(
            crate_annotation,
            &annotations.metadata.packages,
            &annotations.lockfile.crates,
            &annotations.pairred_extras,
            &annotations.crate_features,
            include_binaries,
            include_build_scripts,
        );

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

    fn package_context_test(
        set_package: fn(package: &mut Package),
        check_context: fn(context: CrateContext),
    ) {
        let mut annotations = common_annotations();
        let crate_annotation = &annotations.metadata.crates[&PackageId {
            repr: "common 0.1.0 (path+file://{TEMP_DIR}/common)".to_owned(),
        }];
        let include_binaries = false;
        let include_build_scripts = false;

        let package = annotations
            .metadata
            .packages
            .get_mut(&crate_annotation.node.id)
            .unwrap();
        set_package(package);

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

        assert_eq!(context.name, "common");
        check_context(context);
    }

    #[test]
    fn context_with_parsable_license() {
        package_context_test(
            |package| {
                package.license = Some("MIT OR Apache-2.0".to_owned());
            },
            |context| {
                assert_eq!(
                    context.license_ids,
                    BTreeSet::from(["MIT".to_owned(), "Apache-2.0".to_owned(),]),
                );
            },
        );
    }

    #[test]
    fn context_with_unparsable_license() {
        package_context_test(
            |package| {
                package.license = Some("NonSPDXLicenseID".to_owned());
            },
            |context| {
                assert_eq!(context.license_ids, BTreeSet::default(),);
            },
        );
    }

    #[test]
    fn context_with_license_file() {
        package_context_test(
            |package| {
                package.license_file = Some("LICENSE.txt".into());
            },
            |context| {
                assert_eq!(context.license_file, Some("LICENSE.txt".to_owned()),);
            },
        );
    }

    #[test]
    fn context_package_url_with_only_repository() {
        package_context_test(
            |package| {
                package.repository = Some("http://www.repostiory.com/".to_owned());
                package.homepage = None;
            },
            |context| {
                assert_eq!(
                    context.package_url,
                    Some("http://www.repostiory.com/".to_owned())
                );
            },
        );
    }

    #[test]
    fn context_package_url_with_only_homepage() {
        package_context_test(
            |package| {
                package.repository = None;
                package.homepage = Some("http://www.homepage.com/".to_owned());
            },
            |context| {
                assert_eq!(
                    context.package_url,
                    Some("http://www.homepage.com/".to_owned())
                );
            },
        );
    }

    #[test]
    fn context_package_url_prefers_repository() {
        package_context_test(
            |package| {
                package.repository = Some("http://www.repostiory.com/".to_owned());
                package.homepage = Some("http://www.homepage.com/".to_owned());
            },
            |context| {
                assert_eq!(
                    context.package_url,
                    Some("http://www.repostiory.com/".to_owned())
                );
            },
        );
    }
}
