// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::{
        cfg::{cfg_to_gn_conditional, target_to_gn_conditional},
        target::GnTarget,
        types::*,
        CombinedTargetCfg, GlobalTargetCfgs, GroupVisibility,
    },
    anyhow::{Context, Error},
    cargo_metadata::Package,
    std::borrow::Cow,
    std::collections::BTreeMap,
    std::fmt::Display,
    std::io,
    std::path::Path,
    std::string::ToString,
};

/// Utility to add a version suffix to a GN target name.
pub fn add_version_suffix(prefix: &str, version: &impl ToString) -> String {
    let mut accum = String::new();
    accum.push_str(&prefix);
    accum.push_str("-v");
    accum.push_str(version.to_string().replace(".", "_").as_str());
    accum
}

/// Write a header for the output GN file
pub fn write_header<W: io::Write>(output: &mut W, _cargo_file: &Path) -> Result<(), Error> {
    writeln!(
        output,
        include_str!("../templates/gn_header.template"),
        // TODO set this, but in a way that tests don't fail on Jan 1st
        year = "2020",
    )
    .map_err(Into::into)
}

/// Write an import stament for the output GN file
pub fn write_import<W: io::Write>(output: &mut W, file_name: &str) -> Result<(), Error> {
    writeln!(output, include_str!("../templates/gn_import.template"), file_name = file_name)
        .map_err(Into::into)
}

/// Writes rules at the top of the GN file that don't have the version appended
pub fn write_top_level_rule<'a, W: io::Write>(
    output: &mut W,
    platform: Option<String>,
    pkg: &Package,
    group_visibility: Option<&GroupVisibility>,
) -> Result<(), Error> {
    let target_name = if pkg.is_proc_macro() {
        format!("{}($host_toolchain)", pkg.gn_name())
    } else {
        pkg.gn_name()
    };
    if let Some(ref platform) = platform {
        writeln!(
            output,
            "if ({conditional}) {{\n",
            conditional = target_to_gn_conditional(&platform)?
        )?;
    }
    let optional_visibility =
        group_visibility.map(|v| format!("visibility = {}", v.variable)).unwrap_or_default();
    writeln!(
        output,
        include_str!("../templates/top_level_gn_rule.template"),
        group_name = pkg.name,
        dep_name = target_name,
        optional_visibility = optional_visibility,
    )?;
    if platform.is_some() {
        writeln!(output, "}}\n")?;
    }
    Ok(())
}

/// Writes rules at the top of the GN file that don't have the version appended
pub fn write_binary_top_level_rule<'a, W: io::Write>(
    output: &mut W,
    platform: Option<String>,
    rule_name: &str,
    target: &GnTarget<'a>,
) -> Result<(), Error> {
    if let Some(ref platform) = platform {
        writeln!(
            output,
            "if ({conditional}) {{\n",
            conditional = cfg_to_gn_conditional(&platform)?
        )?;
    }
    writeln!(
        output,
        include_str!("../templates/top_level_binary_gn_rule.template"),
        group_name = rule_name,
        dep_name = target.gn_target_name(),
    )?;
    if platform.is_some() {
        writeln!(output, "}}\n")?;
    }
    Ok(())
}

struct GnField {
    ty: String,
    exists: bool,
    // Use BTreeMap so that iteration over platforms is stable.
    add_fields: BTreeMap<Option<Platform>, Vec<String>>,
    remove_fields: BTreeMap<Option<Platform>, Vec<String>>,
}
impl GnField {
    /// If defining a new field in the template
    pub fn new(ty: &str) -> GnField {
        GnField {
            ty: ty.to_string(),
            exists: false,
            add_fields: BTreeMap::new(),
            remove_fields: BTreeMap::new(),
        }
    }

    /// If the field already exists in the template
    pub fn exists(ty: &str) -> GnField {
        GnField { exists: true, ..Self::new(ty) }
    }

    pub fn add_platform_cfg<T: AsRef<str> + Display>(&mut self, platform: Option<String>, cfg: T) {
        let field = self.add_fields.entry(platform).or_insert(vec![]);
        field.push(format!("\"{}\"", cfg));
    }

    pub fn remove_platform_cfg<T: AsRef<str> + Display>(
        &mut self,
        platform: Option<String>,
        cfg: T,
    ) {
        let field = self.remove_fields.entry(platform).or_insert(vec![]);
        field.push(format!("\"{}\"", cfg));
    }

    pub fn add_cfg<T: AsRef<str> + Display>(&mut self, cfg: T) {
        self.add_platform_cfg(None, cfg)
    }

    pub fn remove_cfg<T: AsRef<str> + Display>(&mut self, cfg: T) {
        self.remove_platform_cfg(None, cfg)
    }

    pub fn render_gn(&self) -> String {
        let mut output = if self.exists {
            // We don't create an empty [] if the field already exists
            match self.add_fields.get(&None) {
                Some(add_fields) => format!("{} += [{}]\n", self.ty, add_fields.join(",")),
                None => "".to_string(),
            }
        } else {
            format!("{} = [{}]\n", self.ty, self.add_fields.get(&None).unwrap_or(&vec![]).join(","))
        };

        // remove platfrom independent configs
        if let Some(rm_fields) = self.remove_fields.get(&None) {
            output.push_str(format!("{} -= [{}]\n", self.ty, rm_fields.join(",")).as_str());
        }

        // Add logic for specific platforms
        for platform in self.add_fields.keys().filter(|k| k.is_some()) {
            output.push_str(
                format!(
                    "if ({}) {{\n",
                    cfg_to_gn_conditional(&platform.as_ref().unwrap()).expect("valid cfg")
                )
                .as_str(),
            );
            output.push_str(
                format!(
                    "{} += [{}]",
                    self.ty,
                    self.add_fields.get(platform).unwrap_or(&vec![]).join(",")
                )
                .as_str(),
            );
            output.push_str("}\n");
        }

        // Remove logic for specific platforms
        for platform in self.remove_fields.keys().filter(|k| k.is_some()) {
            output.push_str(
                format!(
                    "if ({}) {{\n",
                    cfg_to_gn_conditional(&platform.as_ref().unwrap()).expect("valid cfg")
                )
                .as_str(),
            );
            output.push_str(
                format!(
                    "{} -= [{}]",
                    self.ty,
                    self.remove_fields.get(platform).unwrap_or(&vec![]).join(",")
                )
                .as_str(),
            );
            output.push_str("}\n");
        }
        output
    }
}

/// Write a Target to the GN file. Includes information from the build script.
pub fn write_rule<W: io::Write>(
    output: &mut W,
    target: &GnTarget<'_>,
    project_root: &Path,
    global_target_cfgs: Option<&GlobalTargetCfgs>,
    custom_build: Option<&CombinedTargetCfg<'_>>,
    output_name: Option<&str>,
) -> Result<(), Error> {
    // Generate a section for dependencies that is paramaterized on toolchain
    let mut dependencies = String::from("deps = []\n");
    let mut aliased_deps = vec![];

    // Stable output of platforms
    let mut platform_deps: Vec<(
        &Option<String>,
        &Vec<(&cargo_metadata::Package, std::string::String)>,
    )> = target.dependencies.iter().collect();
    platform_deps.sort_by(|p, p2| p.0.cmp(p2.0));

    for (platform, deps) in platform_deps {
        // sort for stable output
        let mut deps = deps.clone();
        deps.sort_by(|a, b| (a.0).id.cmp(&(b.0).id));

        // TODO(bwb) feed GN toolchain mapping in as a configuration to make more generic
        match platform.as_ref().map(String::as_str) {
            None => {
                for pkg in deps {
                    dependencies.push_str("  deps += [");
                    if pkg.0.is_proc_macro() {
                        dependencies.push_str(
                            format!("\":{}($host_toolchain)\"", pkg.0.gn_name()).as_str(),
                        );
                    } else {
                        dependencies.push_str(format!("\":{}\"", pkg.0.gn_name()).as_str());
                    }
                    dependencies.push_str("]\n");
                    if pkg.0.name.replace("-", "_") != pkg.1 {
                        aliased_deps.push(format!("{} = \":{}\" ", pkg.1, pkg.0.gn_name()));
                    }
                }
            }
            Some(platform) => {
                dependencies.push_str(
                    format!("if ({}) {{\n", target_to_gn_conditional(platform)?).as_str(),
                );
                for pkg in deps {
                    dependencies.push_str("  deps += [");
                    if pkg.0.is_proc_macro() {
                        dependencies.push_str(
                            format!("\":{}($host_toolchain)\"", pkg.0.gn_name()).as_str(),
                        );
                    } else {
                        dependencies.push_str(format!("\":{}\"", pkg.0.gn_name()).as_str());
                    }
                    dependencies.push_str("]\n");

                    if pkg.0.name.replace("-", "_") != pkg.1 {
                        aliased_deps.push(format!("{} = \":{}\" ", pkg.1, pkg.0.gn_name()));
                    }
                }
                dependencies.push_str("}\n");
            }
        }
    }

    // write the features into the configs
    let mut rustflags = GnField::new("rustflags");
    let mut rustenv = GnField::new("rustenv");
    let mut configs = GnField::exists("configs");

    if let Some(global_cfg) = global_target_cfgs {
        for cfg in &global_cfg.remove_cfgs {
            configs.remove_cfg(cfg);
        }
        for cfg in &global_cfg.add_cfgs {
            configs.add_cfg(cfg);
        }
    }

    // Associate unique metadata with this crate
    rustflags.add_cfg("--cap-lints=allow");
    rustflags.add_cfg(format!("--edition={}", target.edition));
    rustflags.add_cfg(format!("-Cmetadata={}", target.metadata_hash()));
    rustflags.add_cfg(format!("-Cextra-filename=-{}", target.metadata_hash()));

    // Aggregate feature flags
    for feature in target.features {
        rustflags.add_cfg(format!("--cfg=feature=\\\"{}\\\"", feature));
    }

    // From the gn custom configs, add flags, env vars, and visibility
    let mut visibility = vec![];

    if let Some(custom_build) = custom_build {
        for (platform, cfg) in custom_build {
            if let Some(ref deps) = cfg.deps {
                for dep in deps {
                    // TODO: Respect dep.platform here.
                    dependencies.push_str(format!("  deps += [\"{}\"]", dep).as_str());
                }
            }
            if let Some(ref flags) = cfg.rustflags {
                for flag in flags {
                    rustflags.add_platform_cfg(platform.cloned(), flag.to_string());
                }
            }
            if let Some(ref env_vars) = cfg.env_vars {
                for flag in env_vars {
                    rustenv.add_platform_cfg(platform.cloned(), flag.to_string());
                }
            }
            if let Some(ref crate_configs) = cfg.configs {
                for config in crate_configs {
                    configs.add_platform_cfg(platform.cloned(), config);
                }
            }
            if let Some(ref vis) = cfg.visibility {
                visibility.extend(vis.iter().map(|v| format!("  visibility += [\"{}\"]", v)));
            }
        }
    }

    let visibility = if visibility.is_empty() {
        String::from("visibility = [\":*\"]\n")
    } else {
        let mut v = String::from("visibility = []\n");
        v.extend(visibility);
        v
    };

    // making the templates more readable.
    let aliased_deps_str = if aliased_deps.len() == 0 {
        String::from("")
    } else {
        format!("aliased_deps = {{{}}}", aliased_deps.join("\n"))
    };

    // GN root relative path
    let root_relative_path = format!(
        "//{}",
        target
            .crate_root
            .strip_prefix(project_root)
            .with_context(|| format!(
                "{} is located outside of the project. Check your vendoring setup",
                target.name()
            ))?
            .to_string()
    );
    let output_name = output_name.map_or_else(
        || Cow::Owned(format!("{}-{}", target.name().replace("-", "_"), target.metadata_hash())),
        |n| Cow::Borrowed(n),
    );
    writeln!(
        output,
        include_str!("../templates/gn_rule.template"),
        gn_rule = target.gn_target_type(),
        target_name = target.gn_target_name(),
        crate_name = target.name().replace("-", "_"),
        output_name = output_name,
        root_path = root_relative_path,
        aliased_deps = aliased_deps_str,
        dependencies = dependencies,
        cfgs = configs.render_gn(),
        rustenv = rustenv.render_gn(),
        rustflags = rustflags.render_gn(),
        visibility = visibility,
    )
    .map_err(Into::into)
}

#[cfg(test)]
mod tests {
    use super::*;
    use camino::Utf8Path;
    use cargo_metadata::Version;
    use std::collections::HashMap;

    #[test]
    fn simple_target() {
        let pkg_id = cargo_metadata::PackageId { repr: String::from("42") };
        let version = Version::new(0, 1, 0);
        let target = GnTarget::new(
            &pkg_id,
            "test_target",
            "test_package",
            "2018",
            Utf8Path::new("somewhere/over/the/rainbow.rs"),
            &version,
            GnRustType::Library,
            &[],
            None,
            HashMap::new(),
        );

        let mut output = vec![];
        write_rule(&mut output, &target, Path::new("somewhere/over"), None, None, None).unwrap();
        let output = String::from_utf8(output).unwrap();
        assert_eq!(
            output,
            r#"rust_library("test_package-v0_1_0") {
  crate_name = "test_target"
  crate_root = "//the/rainbow.rs"
  output_name = "test_target-c5bf97c44457465a"
  
  deps = []

  rustenv = []

  rustflags = ["--cap-lints=allow","--edition=2018","-Cmetadata=c5bf97c44457465a","-Cextra-filename=-c5bf97c44457465a"]

  
  visibility = [":*"]

}

"#
        );
    }
    #[test]
    fn binary_target() {
        let pkg_id = cargo_metadata::PackageId { repr: String::from("42") };
        let version = Version::new(0, 1, 0);
        let target = GnTarget::new(
            &pkg_id,
            "test_target",
            "test_package",
            "2018",
            Utf8Path::new("somewhere/over/the/rainbow.rs"),
            &version,
            GnRustType::Binary,
            &[],
            None,
            HashMap::new(),
        );

        let outname = Some("rainbow_binary");
        let mut output = vec![];
        write_rule(&mut output, &target, Path::new("somewhere/over"), None, None, outname).unwrap();
        let output = String::from_utf8(output).unwrap();
        assert_eq!(
            output,
            r#"executable("test_package-test_target-v0_1_0") {
  crate_name = "test_target"
  crate_root = "//the/rainbow.rs"
  output_name = "rainbow_binary"
  
  deps = []

  rustenv = []

  rustflags = ["--cap-lints=allow","--edition=2018","-Cmetadata=bf8f4a806276c599","-Cextra-filename=-bf8f4a806276c599"]

  
  visibility = [":*"]

}

"#
        );
    }
}
