// 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.
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#"}}

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(())
}
