// 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::target::GnTarget,
    anyhow::{anyhow, Result},
    std::process::Command,
    std::{path::PathBuf, str::FromStr},
};

pub struct BuildScriptOutput {
    pub rustflags: Vec<String>,
    pub rustenv: Vec<String>,
}

impl BuildScriptOutput {
    pub fn parse_from_file(file: PathBuf) -> Result<Self> {
        let contents = std::fs::read_to_string(file)?;
        let configs: Vec<&str> = contents.split('\n').collect();
        Ok(Self::parse(configs))
    }

    pub fn parse(lines: Vec<&str>) -> Self {
        let mut bs = BuildScriptOutput { rustflags: vec![], rustenv: vec![] };

        for line in lines {
            if line.is_empty() {
                continue;
            }

            let keyval = line.strip_prefix("cargo:");
            if keyval.is_none() {
                eprintln!("warning: build script output includes non-cargo lines: {}", line);
                continue;
            }

            // More information on the available cargo instructions is here:
            // https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script
            //
            // The following cases are currently unsupported. They all have to do with specific
            // artifact type link arguments. The more general cargo:rustc-link-arg is covered.
            //
            // cargo:rustc-link-arg-bin=BIN=FLAG — Passes custom flags to a linker for the
            // binary BIN.
            //
            // cargo:rustc-link-arg-bins=FLAG — Passes custom flags to a linker for binaries.
            //
            // cargo:rustc-link-arg-tests=FLAG — Passes custom flags to a linker for tests.
            //
            // cargo:rustc-link-arg-examples=FLAG — Passes custom flags to a linker for
            // examples.
            //
            // cargo:rustc-link-arg-benches=FLAG — Passes custom flags to a linker for
            // benchmarks.
            //
            // cargo:rustc-cdylib-link-arg=FLAG — Passes custom flags to a linker for cdylib crates.

            let (key, value) = keyval.unwrap().split_once('=').unwrap();
            match key {
                "rerun-if-changed" => continue, // ignored because these are always vendored
                "rerun-if-env-changed" => continue, // ignored because these are always vendored
                "rustc-cfg" => bs.rustflags.push(format!("\"--cfg={}\"", value)),
                "rustc-env" => bs.rustenv.push(format!("\"{}\"", value.to_string())),
                "rustc-flags" => bs.rustflags.push(format!("\"{}\"", value.to_string())),
                "rustc-link-arg" => bs.rustflags.push(format!("\"-C link-arg={}\"", value)),
                "rustc-link-lib" => bs.rustflags.push(format!("\"-l {}\"", value)),
                // "rustc-link-search" => bs.rustflags.push(format!("-L {}", value)),
                "warning" => eprintln!("warning: {}", value),
                &_ => eprintln!("warning: unable to parse build script output: {}", value),
            }
        }

        bs
    }
}

pub struct BuildScript {}

impl BuildScript {
    pub fn execute(target: &GnTarget<'_>) -> Result<BuildScriptOutput> {
        // Previously, this code would compile build.rs scripts directly with rustc. However, build
        // scripts can have dependencies of their own (e.g. build-dependencies in Cargo.toml).
        // Rather than resolve the entire dependency chain ourselves, we call out to cargo to build
        // the crate, performing the build.rs compilation along the way. This does more work than
        // compiling the build.rs directly but we don't want to get into the dependency resolution
        // business when cargo can do this already.
        //
        // Unfortunately, there is no way to tell cargo to build only the build script. We could
        // link in the cargo library itself and call the correct functions to do only that part of
        // the build but that seems overkill.
        let cargo = std::env::var_os("CARGO").unwrap_or_else(|| std::ffi::OsString::from("cargo"));

        let command = Command::new(cargo)
            .current_dir(target.package_root())
            .arg("check")
            .arg("--message-format=json-render-diagnostics")
            .output()
            .expect("failed to execute cargo crate build");

        if !command.status.success() {
            return Err(anyhow!(
                "Failed to compile {}:\n{}",
                target.gn_target_name(),
                String::from_utf8_lossy(&command.stderr)
            ));
        }

        let stdout = String::from_utf8(command.stdout)?;
        let messages: Vec<&str> = stdout.trim().split('\n').collect();
        for message in messages {
            let json: serde_json::Value =
                serde_json::from_str(message).expect("JSON was not well-formatted");

            let reason = json.get("reason").unwrap();
            if reason != "build-script-executed" {
                continue;
            }

            let package_id = json.get("package_id").unwrap().to_string().replace('"', "");
            let package_elements: Vec<&str> = package_id.split(' ').collect();
            let crate_name = package_elements[0];

            // this build script execution was for the crate that we are expecting to have a
            // build script (avoids issues where a dependency has a build script and we use
            // that one by mistake)
            if crate_name != target.target_name {
                continue;
            }

            // cargo executes the build script for us and stores the output in its cache, we just
            // need to parse it
            let out_dir = json.get("out_dir").unwrap().as_str().unwrap();
            let output = PathBuf::from_str(out_dir).unwrap().parent().unwrap().join("output");
            return BuildScriptOutput::parse_from_file(output);
        }

        Err(anyhow!(
            "We detected a build script in {} but cargo didn't compile it",
            target.gn_target_name()
        ))
    }
}
