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

// Provides tools for generating a Rust library with D-Bus bindings. The generated bindings are
// included in the published crate since the source XML files are only available from the original
// path or the ebuild. See the README.md for usage.

use std::env;
use std::fmt::{self, Debug, Display};
use std::fs::{create_dir_all, remove_dir_all, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::Command;

const DEFAULT_BINDINGS_DIR: &str = "src/bindings";
const DEFAULT_CLIENT_OPTS: &[&str] = &["-s", "-m", "None"];
const DEFAULT_SERVER_OPTS: &[&str] = &["-s", "-m", "Fn", "-a", "RefClosure"];

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BindingsType {
    Client,
    Server,
    Both,
}

#[derive(Debug)]
pub enum Error {
    CleanupFailed(io::Error),
    CommandFailed(Option<i32>),
    Create(io::Error),
    CreateDirAll(io::Error),
    Generate(String),
    Open(io::Error),
    SourceDoesntExist(PathBuf),
    Spawn(io::Error),
    Wait(io::Error),
    Write(io::Error),
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            CleanupFailed(e) => write!(f, "failed to cleanup old bindings: {}", e),
            CommandFailed(o) => match o {
                Some(c) => write!(f, "command failed with code {}", c),
                None => write!(f, "command failed"),
            },
            Create(e) => write!(f, "create failed: {}", e),
            CreateDirAll(e) => write!(f, "create_dir_all failed: {}", e),
            Generate(s) => write!(f, "generate failed: {}", s),
            Open(e) => write!(f, "open failed: {}", e),
            SourceDoesntExist(file) => match file.to_str() {
                None => write!(f, "empty path"),
                Some(s) => write!(f, "source file doesn't exist: {}", s),
            },
            Spawn(e) => write!(f, "spawn failed: {}", e),
            Wait(e) => write!(f, "wait failed: {}", e),
            Write(e) => write!(f, "write error: {}", e),
        }
    }
}

/// The result of an operation in this crate.
pub type Result<T> = std::result::Result<T, Error>;

// Include generated bindings.
fn include_module(mod_out: &mut File, module: &str) -> Result<()> {
    writeln!(
        mod_out,
        "  pub mod {module};\n  pub use {module}::*;",
        module = module
    )
    .map_err(Error::Write)
}

// sub_modules: &[(<module name>, <relative path to source xml>), ...]
pub fn generate_module(
    source_dir: &Path,
    sub_modules: &[(&str, &str, BindingsType)],
) -> Result<()> {
    let bindings_dir = PathBuf::from(DEFAULT_BINDINGS_DIR);
    let client_dir = bindings_dir.join("client");
    let server_dir = bindings_dir.join("server");

    let mut errors: String = String::new();

    // If the bindings exist and it is a release build exit early.
    if bindings_dir.exists() {
        if env::var("PROFILE").map_or(false, |v| &v == "release") {
            return Ok(());
        }
        remove_dir_all(&bindings_dir).map_err(Error::CleanupFailed)?;
    }
    create_dir_all(&client_dir).map_err(Error::CreateDirAll)?;
    create_dir_all(&server_dir).map_err(Error::CreateDirAll)?;

    // Write header of include file.
    let mut mod_out =
        File::create(bindings_dir.join("include_modules.rs")).map_err(Error::Create)?;
    writeln!(
        mod_out,
        r#"// Do not edit. This is generated by system_api/build.rs.
#[allow(clippy::all)]
pub mod client {{"#
    )
    .map_err(Error::Write)?;

    for (module, source, bindings_type) in sub_modules {
        match bindings_type {
            BindingsType::Client | BindingsType::Both => {}
            BindingsType::Server => {
                continue;
            }
        }
        // Generate bindings if they don't already exist.
        let destination = client_dir.join(format!("{}.rs", module));
        if !destination.exists() {
            if let Err(err) =
                generate_bindings(&source_dir.join(source), &destination, DEFAULT_CLIENT_OPTS)
            {
                errors.push_str(&format!(
                    "Failed to generate {:?} from {:?}: {}\n",
                    module, source, err
                ));
                // Canonicalize will fail if the destination doesn't exist.
                continue;
            }
        }
        include_module(&mut mod_out, module)?;
    }
    writeln!(
        mod_out,
        r#"}}

#[allow(clippy::all)]
pub mod server {{"#
    )
    .map_err(Error::Write)?;
    for (module, source, bindings_type) in sub_modules {
        match bindings_type {
            BindingsType::Server | BindingsType::Both => {}
            BindingsType::Client => {
                continue;
            }
        }
        // Generate bindings if they don't already exist.
        let destination = server_dir.join(format!("{}.rs", module));
        if !destination.exists() {
            if let Err(err) =
                generate_bindings(&source_dir.join(source), &destination, DEFAULT_SERVER_OPTS)
            {
                errors.push_str(&format!(
                    "Failed to generate {:?} from {:?}: {}\n",
                    module, source, err
                ));
                // Canonicalize will fail if the destination doesn't exist.
                continue;
            }
        }
        include_module(&mut mod_out, module)?;
    }
    writeln!(mod_out, "}}").map_err(Error::Write)?;

    if errors.is_empty() {
        Ok(())
    } else {
        Err(Error::Generate(errors))
    }
}

fn generate_bindings(source: &Path, destination: &Path, opts: &[&str]) -> Result<()> {
    if !source.exists() {
        return Err(Error::SourceDoesntExist(source.to_path_buf()));
    }
    let status = Command::new("dbus-codegen-rust")
        .args(opts)
        .stdin(File::open(source).map_err(Error::Open)?)
        .stdout(File::create(destination).map_err(Error::Create)?)
        .spawn()
        .map_err(Error::Spawn)?
        .wait()
        .map_err(Error::Wait)?;
    if !status.success() {
        return Err(Error::CommandFailed(status.code()));
    }
    Ok(())
}
