// Copyright 2017 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::sdk::{fuchsia_dir, fx_path, target_out_dir, FuchsiaConfig, TargetOptions};
use crate::utils::is_mac;
use failure::{bail, err_msg, Error, ResultExt};
use std::env;
use std::path::Path;
use std::process::{Command, Stdio};
use std::{str, thread, time};

pub fn netaddr(verbose: bool, target_options: &TargetOptions<'_, '_>) -> Result<String, Error> {
    let fx_script = fx_path()?;
    if !fx_script.exists() {
        bail!("fx script not found at {:?}", fx_script);
    }

    let mut args = vec!["netaddr", "--fuchsia", "--timeout=500", "--nowait"];
    if let Some(device_name) = target_options.device_name {
        args.push(device_name);
    }
    let netaddr_result = Command::new(fx_script).args(args).output()?;
    let result = str::from_utf8(&netaddr_result.stdout)?.trim().to_string();
    if verbose {
        println!("netaddr status = {}, result = {}", netaddr_result.status, result);
    }
    if !netaddr_result.status.success() {
        let err_str = str::from_utf8(&netaddr_result.stderr)?.trim().to_string();
        bail!("netaddr failed with status {:?}: {}", netaddr_result.status, err_str);
    }
    Ok(result)
}

pub fn netls(verbose: bool) -> Result<(), Error> {
    let fx_script = fx_path()?;
    if !fx_script.exists() {
        bail!("fx script not found at {:?}", fx_script);
    }

    let mut netls_command = Command::new(fx_script);
    netls_command.arg("netls").arg("--nowait").arg("--timeout=500");
    if verbose {
        println!("{:?}", netls_command);
    }
    let netls_status = netls_command.status()?;
    if !netls_status.success() {
        bail!("netlst failed with error {:?}", netls_status);
    }
    Ok(())
}

static SSH_OPTIONS: &'static [&str] = &[
    "-o",
    "UserKnownHostsFile=/dev/null",
    "-o",
    "StrictHostKeyChecking=no",
    "-o",
    "ConnectTimeout=20",
];

pub fn ssh(
    verbose: bool,
    config: &FuchsiaConfig,
    target_options: &TargetOptions<'_, '_>,
    command: &str,
) -> Result<(), Error> {
    let netaddr = netaddr(verbose, target_options).context("netaddr failed")?;
    let ssh_config = target_out_dir(config)?.join("ssh-keys/ssh_config");
    if !ssh_config.exists() {
        bail!("ssh config not found at {:?}", ssh_config);
    }
    let ssh_result = Command::new("ssh")
        .env_remove("SSH_AUTH_SOCK")
        .arg("-q")
        .arg("-F")
        .arg(ssh_config)
        .args(SSH_OPTIONS)
        .arg(netaddr)
        .arg(command)
        .status()
        .context("unable to run ssh")?;

    if !ssh_result.success() {
        bail!("ssh failed: {}", ssh_result);
    }

    Ok(())
}

pub fn setup_network_mac(user: &str) -> Result<(), Error> {
    println!("Calling sudo ifconfig to bring up tap0 interface; password may be required.");

    let chown_status = Command::new("sudo")
        .arg("chown")
        .arg(user)
        .arg("/dev/tap0")
        .status()
        .context("couldn't run chown")?;

    if !chown_status.success() {
        bail!("chown failed: {}", chown_status);
    }

    let mut loop_count = 0;
    loop {
        let ifconfig_status = Command::new("sudo")
            .arg("ifconfig")
            .arg("tap0")
            .arg("inet6")
            .arg("fc00::/7")
            .arg("up")
            .status()
            .context("couldn't run ifconfig")?;

        if !ifconfig_status.success() {
            if loop_count > 10 {
                bail!("ifconfig failed: {}", ifconfig_status);
            }
            loop_count += 1;
            thread::sleep(time::Duration::from_millis(300));
        } else {
            break;
        }
    }

    println!("tap0 enabled");

    Ok(())
}

#[cfg_attr(rustfmt, rustfmt_skip)]
static TUNCTL_NOT_FOUND_ERROR: &'static str =
"tunctl command not found. Please install uml-utilities.
For help see https://fuchsia.googlesource.com/zircon/+/
master/docs/qemu.md#Enabling-Networking-under-QEMU-x86_64-only";

pub fn setup_network_linux(user: &str) -> Result<(), Error> {
    // Create the tap network device if it doesn't exist.
    if !Path::new("/sys/class/net/qemu").exists() {
        println!(
            "Qemu tap device not found. Using sudo and tunctl to create tap network device; \
             password may be required."
        );
        let tunctl_status = Command::new("sudo")
            .args(&["tunctl", "-b", "-u", user, "-t", "qemu"])
            .stdout(Stdio::null())
            .status()
            .map_err(|e| {
                if e.kind() == ::std::io::ErrorKind::NotFound {
                    err_msg(TUNCTL_NOT_FOUND_ERROR)
                } else {
                    err_msg("tunctl failed to create a new tap network device")
                }
            })?;

        if !tunctl_status.success() {
            bail!("tunctl failed to create tap network device.");
        }
    }

    let ifconfig_status = Command::new("sudo")
        .arg("ifconfig")
        .arg("qemu")
        .arg("up")
        .status()
        .context("couldn't run ifconfig")?;

    if !ifconfig_status.success() {
        bail!("ifconfig failed");
    }

    Ok(())
}

pub fn setup_network() -> Result<(), Error> {
    let user = env::var("USER").context("No $USER env var found.")?;
    if is_mac() {
        setup_network_mac(&user)?;
    } else {
        setup_network_linux(&user)?;
    }
    Command::new("stty").arg("sane").status().context("couldn't run stty")?;
    Ok(())
}

pub struct StartEmulatorOptions {
    pub verbose: bool,
    pub aemu: bool,
    pub with_graphics: bool,
    pub with_acceleration: bool,
    pub with_networking: bool,
    pub disable_virtcon: bool,
}

pub fn start_emulator(options: &StartEmulatorOptions, params: &[&str]) -> Result<(), Error> {
    let fuchsia_dir = fuchsia_dir()?;
    let fx_script = fx_path()?;
    if !fx_script.exists() {
        bail!("fx script not found at {:?}", fx_script);
    }

    let mut args = vec![];
    if options.aemu {
        args.push("emu");
    } else {
        args.push("qemu");
    }

    if options.with_networking {
        args.push("-N");
    }

    if options.with_graphics {
        if !options.aemu {
            args.push("-g");
        }
    } else {
        if options.aemu {
            args.push("--headless");
        }
    }

    if options.with_acceleration {
        if options.aemu {
            args.push("-a");
            if is_mac() {
                args.push("hax");
            } else {
                args.push("kvm");
            }
        } else {
            args.push("-k");
        }
    } else {
        if options.aemu {
            args.push("-a");
            args.push("off");
        }
    }

    if options.disable_virtcon {
        args.push("-c");
        args.push("virtcon.disable");
    }

    if options.verbose {
        println!("fx_script = {:?}", fx_script);
        println!("args = {:?}", args);
        println!("params = {:?}", params);
    }

    let child = Command::new(fx_script)
        .args(&args)
        .args(params)
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .current_dir(&fuchsia_dir)
        .spawn()
        .context("unable to run qemu")?;

    println!("emulator started with process ID {}", child.id());

    if options.with_networking {
        setup_network()
    } else {
        Ok(())
    }
}

pub fn stop_emulator() -> Result<(), Error> {
    let reg_ex_flag = if is_mac() { "-m" } else { "-r" };
    Command::new("killall").arg("-9").arg(reg_ex_flag).arg("qemu-system-x86_64.*").status()?;
    Ok(())
}

pub fn enable_networking() -> Result<(), Error> {
    setup_network()
}
