// SPDX-License-Identifier: Apache-2.0

extern crate glob;

use std::cell::RefCell;
use std::collections::HashMap;
use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;

use glob::{MatchOptions, Pattern};

//================================================
// Commands
//================================================

thread_local! {
    /// The errors encountered by the build script while executing commands.
    static COMMAND_ERRORS: RefCell<HashMap<String, Vec<String>>> = RefCell::default();
}

/// Adds an error encountered by the build script while executing a command.
fn add_command_error(name: &str, path: &str, arguments: &[&str], message: String) {
    COMMAND_ERRORS.with(|e| {
        e.borrow_mut()
            .entry(name.into())
            .or_insert_with(Vec::new)
            .push(format!(
                "couldn't execute `{} {}` (path={}) ({})",
                name,
                arguments.join(" "),
                path,
                message,
            ))
    });
}

/// A struct that prints the errors encountered by the build script while
/// executing commands when dropped (unless explictly discarded).
///
/// This is handy because we only want to print these errors when the build
/// script fails to link to an instance of `libclang`. For example, if
/// `llvm-config` couldn't be executed but an instance of `libclang` was found
/// anyway we don't want to pollute the build output with irrelevant errors.
#[derive(Default)]
pub struct CommandErrorPrinter {
    discard: bool,
}

impl CommandErrorPrinter {
    pub fn discard(mut self) {
        self.discard = true;
    }
}

impl Drop for CommandErrorPrinter {
    fn drop(&mut self) {
        if self.discard {
            return;
        }

        let errors = COMMAND_ERRORS.with(|e| e.borrow().clone());

        if let Some(errors) = errors.get("llvm-config") {
            println!(
                "cargo:warning=could not execute `llvm-config` one or more \
                times, if the LLVM_CONFIG_PATH environment variable is set to \
                a full path to valid `llvm-config` executable it will be used \
                to try to find an instance of `libclang` on your system: {}",
                errors
                    .iter()
                    .map(|e| format!("\"{}\"", e))
                    .collect::<Vec<_>>()
                    .join("\n  "),
            )
        }

        if let Some(errors) = errors.get("xcode-select") {
            println!(
                "cargo:warning=could not execute `xcode-select` one or more \
                times, if a valid instance of this executable is on your PATH \
                it will be used to try to find an instance of `libclang` on \
                your system: {}",
                errors
                    .iter()
                    .map(|e| format!("\"{}\"", e))
                    .collect::<Vec<_>>()
                    .join("\n  "),
            )
        }
    }
}

#[cfg(test)]
pub static RUN_COMMAND_MOCK: std::sync::Mutex<
    Option<Box<dyn Fn(&str, &str, &[&str]) -> Option<String> + Send + Sync + 'static>>,
> = std::sync::Mutex::new(None);

/// Executes a command and returns the `stdout` output if the command was
/// successfully executed (errors are added to `COMMAND_ERRORS`).
fn run_command(name: &str, path: &str, arguments: &[&str]) -> Option<String> {
    #[cfg(test)]
    if let Some(command) = &*RUN_COMMAND_MOCK.lock().unwrap() {
        return command(name, path, arguments);
    }

    let output = match Command::new(path).args(arguments).output() {
        Ok(output) => output,
        Err(error) => {
            let message = format!("error: {}", error);
            add_command_error(name, path, arguments, message);
            return None;
        }
    };

    if output.status.success() {
        Some(String::from_utf8_lossy(&output.stdout).into_owned())
    } else {
        let message = format!("exit code: {}", output.status);
        add_command_error(name, path, arguments, message);
        None
    }
}

/// Executes the `llvm-config` command and returns the `stdout` output if the
/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
pub fn run_llvm_config(arguments: &[&str]) -> Option<String> {
    let path = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".into());
    run_command("llvm-config", &path, arguments)
}

/// Executes the `xcode-select` command and returns the `stdout` output if the
/// command was successfully executed (errors are added to `COMMAND_ERRORS`).
pub fn run_xcode_select(arguments: &[&str]) -> Option<String> {
    run_command("xcode-select", "xcode-select", arguments)
}

//================================================
// Search Directories
//================================================
// These search directories are listed in order of
// preference, so if multiple `libclang` instances
// are found when searching matching directories,
// the `libclang` instances from earlier
// directories will be preferred (though version
// takes precedence over location).
//================================================

/// `libclang` directory patterns for Haiku.
const DIRECTORIES_HAIKU: &[&str] = &[
    "/boot/home/config/non-packaged/develop/lib",
    "/boot/home/config/non-packaged/lib",
    "/boot/system/non-packaged/develop/lib",
    "/boot/system/non-packaged/lib",
    "/boot/system/develop/lib",
    "/boot/system/lib",
];

/// `libclang` directory patterns for Linux (and FreeBSD).
const DIRECTORIES_LINUX: &[&str] = &[
    "/usr/local/llvm*/lib*",
    "/usr/local/lib*/*/*",
    "/usr/local/lib*/*",
    "/usr/local/lib*",
    "/usr/lib*/*/*",
    "/usr/lib*/*",
    "/usr/lib*",
];

/// `libclang` directory patterns for macOS.
const DIRECTORIES_MACOS: &[&str] = &[
    "/usr/local/opt/llvm*/lib/llvm*/lib",
    "/Library/Developer/CommandLineTools/usr/lib",
    "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib",
    "/usr/local/opt/llvm*/lib",
];

/// `libclang` directory patterns for Windows.
///
/// The boolean indicates whether the directory pattern should be used when
/// compiling for an MSVC target environment.
const DIRECTORIES_WINDOWS: &[(&str, bool)] = &[
    // LLVM + Clang can be installed using Scoop (https://scoop.sh).
    // Other Windows package managers install LLVM + Clang to other listed
    // system-wide directories.
    ("C:\\Users\\*\\scoop\\apps\\llvm\\current\\lib", true),
    ("C:\\MSYS*\\MinGW*\\lib", false),
    ("C:\\Program Files*\\LLVM\\lib", true),
    ("C:\\LLVM\\lib", true),
    // LLVM + Clang can be installed as a component of Visual Studio.
    // https://github.com/KyleMayes/clang-sys/issues/121
    ("C:\\Program Files*\\Microsoft Visual Studio\\*\\BuildTools\\VC\\Tools\\Llvm\\**\\lib", true),
];

/// `libclang` directory patterns for illumos
const DIRECTORIES_ILLUMOS: &[&str] = &[
    "/opt/ooce/llvm-*/lib",
    "/opt/ooce/clang-*/lib",
];

//================================================
// Searching
//================================================

/// Finds the files in a directory that match one or more filename glob patterns
/// and returns the paths to and filenames of those files.
fn search_directory(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
    // Escape the specified directory in case it contains characters that have
    // special meaning in glob patterns (e.g., `[` or `]`).
    let directory = Pattern::escape(directory.to_str().unwrap());
    let directory = Path::new(&directory);

    // Join the escaped directory to the filename glob patterns to obtain
    // complete glob patterns for the files being searched for.
    let paths = filenames
        .iter()
        .map(|f| directory.join(f).to_str().unwrap().to_owned());

    // Prevent wildcards from matching path separators to ensure that the search
    // is limited to the specified directory.
    let mut options = MatchOptions::new();
    options.require_literal_separator = true;

    paths
        .map(|p| glob::glob_with(&p, options))
        .filter_map(Result::ok)
        .flatten()
        .filter_map(|p| {
            let path = p.ok()?;
            let filename = path.file_name()?.to_str().unwrap();

            // The `libclang_shared` library has been renamed to `libclang-cpp`
            // in Clang 10. This can cause instances of this library (e.g.,
            // `libclang-cpp.so.10`) to be matched by patterns looking for
            // instances of `libclang`.
            if filename.contains("-cpp.") {
                return None;
            }

            Some((directory.to_owned(), filename.into()))
        })
        .collect::<Vec<_>>()
}

/// Finds the files in a directory (and any relevant sibling directories) that
/// match one or more filename glob patterns and returns the paths to and
/// filenames of those files.
fn search_directories(directory: &Path, filenames: &[String]) -> Vec<(PathBuf, String)> {
    let mut results = search_directory(directory, filenames);

    // On Windows, `libclang.dll` is usually found in the LLVM `bin` directory
    // while `libclang.lib` is usually found in the LLVM `lib` directory. To
    // keep things consistent with other platforms, only LLVM `lib` directories
    // are included in the backup search directory globs so we need to search
    // the LLVM `bin` directory here.
    if target_os!("windows") && directory.ends_with("lib") {
        let sibling = directory.parent().unwrap().join("bin");
        results.extend(search_directory(&sibling, filenames).into_iter());
    }

    results
}

/// Finds the `libclang` static or dynamic libraries matching one or more
/// filename glob patterns and returns the paths to and filenames of those files.
pub fn search_libclang_directories(filenames: &[String], variable: &str) -> Vec<(PathBuf, String)> {
    // Search only the path indicated by the relevant environment variable
    // (e.g., `LIBCLANG_PATH`) if it is set.
    if let Ok(path) = env::var(variable).map(|d| Path::new(&d).to_path_buf()) {
        // Check if the path is a matching file.
        if let Some(parent) = path.parent() {
            let filename = path.file_name().unwrap().to_str().unwrap();
            let libraries = search_directories(parent, filenames);
            if libraries.iter().any(|(_, f)| f == filename) {
                return vec![(parent.into(), filename.into())];
            }
        }

        // Check if the path is directory containing a matching file.
        return search_directories(&path, filenames);
    }

    let mut found = vec![];

    // Search the `bin` and `lib` directories in the directory returned by
    // `llvm-config --prefix`.
    if let Some(output) = run_llvm_config(&["--prefix"]) {
        let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
        found.extend(search_directories(&directory.join("bin"), filenames));
        found.extend(search_directories(&directory.join("lib"), filenames));
        found.extend(search_directories(&directory.join("lib64"), filenames));
    }

    // Search the toolchain directory in the directory returned by
    // `xcode-select --print-path`.
    if target_os!("macos") {
        if let Some(output) = run_xcode_select(&["--print-path"]) {
            let directory = Path::new(output.lines().next().unwrap()).to_path_buf();
            let directory = directory.join("Toolchains/XcodeDefault.xctoolchain/usr/lib");
            found.extend(search_directories(&directory, filenames));
        }
    }

    // Search the directories in the `LD_LIBRARY_PATH` environment variable.
    if let Ok(path) = env::var("LD_LIBRARY_PATH") {
        for directory in env::split_paths(&path) {
            found.extend(search_directories(&directory, filenames));
        }
    }

    // Determine the `libclang` directory patterns.
    let directories: Vec<&str> = if target_os!("haiku") {
        DIRECTORIES_HAIKU.into()
    } else if target_os!("linux") || target_os!("freebsd") {
        DIRECTORIES_LINUX.into()
    } else if target_os!("macos") {
        DIRECTORIES_MACOS.into()
    } else if target_os!("windows") {
        let msvc = target_env!("msvc");
        DIRECTORIES_WINDOWS
            .iter()
            .filter(|d| d.1 || !msvc)
            .map(|d| d.0)
            .collect()
    } else if target_os!("illumos") {
        DIRECTORIES_ILLUMOS.into()
    } else {
        vec![]
    };

    // We use temporary directories when testing the build script so we'll
    // remove the prefixes that make the directories absolute.
    let directories = if test!() {
        directories
            .iter()
            .map(|d| d.strip_prefix('/').or_else(|| d.strip_prefix("C:\\")).unwrap_or(d))
            .collect::<Vec<_>>()
    } else {
        directories
    };

    // Search the directories provided by the `libclang` directory patterns.
    let mut options = MatchOptions::new();
    options.case_sensitive = false;
    options.require_literal_separator = true;
    for directory in directories.iter() {
        if let Ok(directories) = glob::glob_with(directory, options) {
            for directory in directories.filter_map(Result::ok).filter(|p| p.is_dir()) {
                found.extend(search_directories(&directory, filenames));
            }
        }
    }

    found
}
