// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::{anyhow, Context as _};
use owo_colors::OwoColorize as _;
use std::{collections, env, ffi, io, io::BufRead, path, process, thread};

pub mod cargo_workspace;
pub mod fuzzers;
pub mod license_checker;

pub fn run_cmd_shell(
    dir: &path::Path,
    cmd: impl AsRef<ffi::OsStr>,
) -> anyhow::Result<SuccessOutput> {
    run_cmd_shell_with_color::<DefaultColors>(dir, cmd)
}

/// Run a shell command using shell arg parsing.
///
/// Removes all `*CARGO*` and `*RUSTUP*` env vars in case this was run with
/// `cargo run`. If they are left in, they confuse nested `cargo` invocations.
///
/// Return Ok if the process completed normally.
pub fn run_cmd_shell_with_color<C: TermColors>(
    dir: &path::Path,
    cmd: impl AsRef<ffi::OsStr>,
) -> anyhow::Result<SuccessOutput> {
    run::<C>(
        dir,
        process::Command::new("sh")
            .current_dir(dir)
            .args(["-c".as_ref(), cmd.as_ref()]),
    )
}

/// Run a cmd with explicit args directly without a shell.
///
/// Removes all `*CARGO*` and `*RUSTUP*` env vars in case this was run with
/// `cargo run`.
///
/// Return Ok if the process completed normally.
#[allow(dead_code)]
pub fn run_cmd<C: TermColors, P, A, S>(
    dir: &path::Path,
    cmd: &P,
    args: A,
) -> anyhow::Result<SuccessOutput>
where
    P: AsRef<path::Path> + ?Sized,
    A: Clone + IntoIterator<Item = S>,
    S: AsRef<ffi::OsStr>,
{
    run::<C>(
        dir,
        process::Command::new(cmd.as_ref())
            .current_dir(dir)
            .args(args),
    )
}

/// Run the specified command.
///
/// `cmd_with_args` is used
fn run<C: TermColors>(
    dir: &path::Path,
    command: &mut process::Command,
) -> Result<SuccessOutput, anyhow::Error> {
    // approximately human readable version of the invocation for logging
    let cmd_with_args = command.get_args().fold(
        command.get_program().to_os_string(),
        |mut acc: ffi::OsString, s| {
            acc.push(" ");
            acc.push(shell_escape::escape(s.to_string_lossy()).as_ref());
            acc
        },
    );

    let context = format!(
        "{} [{}]",
        cmd_with_args.to_string_lossy(),
        dir.to_string_lossy(),
    );
    println!(
        "[{}] [{}]",
        cmd_with_args.to_string_lossy().green(),
        dir.to_string_lossy().blue()
    );

    let mut child = command
        .env_clear()
        .envs(modified_cmd_env())
        .stdin(process::Stdio::null())
        .stdout(process::Stdio::piped())
        .stderr(process::Stdio::piped())
        .spawn()
        .context(context.clone())?;

    // If thread creation overhead becomes a problem, we could always use a shared context
    // that holds on to some channels.
    let stdout_thread = spawn_print_thread::<C::StdoutColor, _, _>(
        child.stdout.take().expect("stdout must be present"),
        io::stdout(),
    );
    let stderr_thread = spawn_print_thread::<C::StderrColor, _, _>(
        child.stderr.take().expect("stderr must be present"),
        io::stderr(),
    );

    let status = child.wait()?;

    let stdout = stdout_thread.join().expect("stdout thread panicked");
    stderr_thread.join().expect("stderr thread panicked");

    match status.code() {
        None => {
            eprintln!("Process terminated by signal");
            Err(anyhow!("Process terminated by signal"))
        }
        Some(0) => Ok(SuccessOutput { stdout }),
        Some(n) => {
            eprintln!("Exit code: {n}");
            Err(anyhow!("Exit code: {n}"))
        }
    }
    .context(context)
}

pub struct SuccessOutput {
    stdout: String,
}

impl SuccessOutput {
    pub fn stdout(&self) -> &str {
        &self.stdout
    }
}

/// Returns modified env vars that are suitable for use in child invocations.
fn modified_cmd_env() -> collections::HashMap<String, String> {
    env::vars()
        // Filter out `*CARGO*` or `*RUSTUP*` vars as those will confuse child invocations of `cargo`.
        .filter(|(k, _)| !(k.contains("CARGO") || k.contains("RUSTUP")))
        // We want colors in our cargo invocations
        .chain([(String::from("CARGO_TERM_COLOR"), String::from("always"))])
        .collect()
}

/// Trait for specifying the terminal text colors of the command output.
pub trait TermColors {
    /// Color for stdout. Use `owo_colors::colors::Default` to keep color codes from the command.
    type StdoutColor: owo_colors::Color;
    /// Color for stderr. Use `owo_colors::colors::Default` to keep color codes from the command.
    type StderrColor: owo_colors::Color;
}

/// Override only the stderr color to yellow.
#[non_exhaustive]
pub struct YellowStderr;

impl TermColors for YellowStderr {
    type StdoutColor = owo_colors::colors::Default;
    type StderrColor = owo_colors::colors::Yellow;
}

/// Keep the default colors from the command output. Typically used with `--color=always` or
/// equivalent env vars like `CARGO_TERM_COLOR` to keep the colors even though the output is not a
/// tty.
#[non_exhaustive]
pub struct DefaultColors;
impl TermColors for DefaultColors {
    type StdoutColor = owo_colors::colors::Default;
    type StderrColor = owo_colors::colors::Default;
}

/// Spawn a thread that will print any lines read from the input using the specified color on
/// the provided writer (intended to be `stdin`/`stdout`.
///
/// The thread accumulates all output lines and returns it
fn spawn_print_thread<C, R, W>(input: R, mut output: W) -> thread::JoinHandle<String>
where
    C: owo_colors::Color,
    R: io::Read + Send + 'static,
    W: io::Write + Send + 'static,
{
    thread::spawn(move || {
        let mut line = String::new();
        let mut all_output = String::new();
        let mut buf_read = io::BufReader::new(input);

        loop {
            line.clear();
            match buf_read.read_line(&mut line) {
                Ok(0) => break,
                Ok(_) => {
                    all_output.push_str(&line);
                    write!(output, "{}", line.fg::<C>()).expect("write to stdio failed");
                }
                // TODO do something smarter for non-UTF8 output
                Err(e) => eprintln!("{}: {:?}", "Could not read line".red(), e),
            }
        }

        all_output
    })
}
