// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#![feature(min_specialization)]
use anyhow::Result;
use atty::Stream;
use directories::ProjectDirs;
use log::LevelFilter;
use serde_annotate::Annotate;
use serde_annotate::ColorProfile;
use std::env::{args_os, ArgsOs};
use std::ffi::OsString;
use std::io::ErrorKind;
use std::iter::{IntoIterator, Iterator};
use std::path::PathBuf;
use structopt::clap::arg_enum;
use structopt::StructOpt;

mod command;
use opentitanlib::app::command::CommandDispatch;
use opentitanlib::app::TransportWrapper;
use opentitanlib::backend;

#[allow(clippy::large_enum_variant)]
#[derive(Debug, StructOpt, CommandDispatch)]
enum RootCommandHierarchy {
    Boot(command::boot::BootCommand),
    // Not flattened because `Bootstrap` is a leaf command.
    Bootstrap(command::bootstrap::BootstrapCommand),
    // Not flattened because `Console` is a leaf command.
    Console(command::console::Console),

    Gpio(command::gpio::GpioCommand),
    Emulator(command::emulator::EmuCommand),

    Fpga(command::fpga::FpgaCommand),
    I2c(command::i2c::I2cCommand),
    Image(command::image::Image),
    NoOp(command::NoOp),
    Otp(command::otp::Otp),
    Rsa(command::rsa::Rsa),
    Spi(command::spi::SpiCommand),
    Transport(command::transport::TransportCommand),
    Version(command::version::Version),

    // Flattened because `Greetings` is a subcommand hierarchy.
    #[cfg(feature = "demo_commands")]
    #[structopt(flatten)]
    Greetings(command::hello::Greetings),
}

arg_enum! {
    #[derive(Clone, Copy, Debug)]
    enum Format {
        Json,
        Json5,
        HJson,
        Yaml,
    }
}

#[derive(Debug, StructOpt)]
#[structopt(
    name = "opentitantool",
    about = "A tool for interacting with OpenTitan chips."
)]
struct Opts {
    #[structopt(
        long,
        default_value = "config",
        help = "Filename of a default flagsfile.  Relative to $XDG_CONFIG_HOME/opentitantool."
    )]
    rcfile: PathBuf,

    #[structopt(long, default_value = "warn")]
    logging: LevelFilter,

    #[structopt(
        short,
        long,
        possible_values = &Format::variants(),
        case_insensitive = true,
        default_value = "hjson",
        help = "Preferred output format"
    )]
    format: Format,

    #[structopt(short, long, parse(try_from_str), help = "Use color in the output")]
    color: Option<bool>,

    #[structopt(
        long,
        number_of_values(1),
        help = "Parse and execute the argument as a command"
    )]
    exec: Vec<String>,

    #[structopt(flatten)]
    backend_opts: backend::BackendOpts,

    #[structopt(subcommand)]
    command: RootCommandHierarchy,
}

// Given some existing option configuration, maybe re-evaluate command
// line options by reading an `rcfile`.
fn parse_command_line(opts: Opts, mut args: ArgsOs) -> Result<Opts> {
    // Initialize the logger if the user requested the non-defualt option.
    let logging = opts.logging;
    if logging != LevelFilter::Off {
        env_logger::Builder::from_default_env()
            .filter(None, opts.logging)
            .init();
    }
    if opts.rcfile.as_os_str().is_empty() {
        // No rcfile to parse.
        return Ok(opts);
    }

    // Construct the rcfile path based on the user's config directory
    // (ie: $HOME/.config/opentitantool/<filename>).
    let rcfile = if let Some(base) = ProjectDirs::from("org", "opentitan", "opentitantool") {
        base.config_dir().join(&opts.rcfile)
    } else {
        opts.rcfile
    };

    // argument[0] is the executable name.
    let mut arguments = vec![args.next().unwrap()];

    // Read in the rcfile and extend the argument list.
    match std::fs::read_to_string(&rcfile) {
        Ok(content) => {
            for line in content.split('\n') {
                // Strip basic comments as shellwords won't handle comments.
                let (line, _) = line.split_once('#').unwrap_or((line, ""));
                arguments.extend(shellwords::split(line)?.iter().map(OsString::from));
            }
            Ok(())
        }
        Err(e) if e.kind() == ErrorKind::NotFound => {
            log::warn!("Could not read {:?}. Ignoring.", rcfile);
            Ok(())
        }
        Err(e) => Err(anyhow::Error::new(e).context(format!("Reading file {:?}", rcfile))),
    }?;

    // Extend the argument list with all remaining command line arguments.
    arguments.extend(args.into_iter());
    let opts = Opts::from_iter(&arguments);
    if opts.logging != logging {
        // Try re-initializing the logger.  Ignore errors.
        let _ = env_logger::Builder::from_default_env()
            .filter(None, opts.logging)
            .try_init();
    }
    Ok(opts)
}

// Print the result of a command.
// If there is an error and `RUST_BACKTRACE=1`, print a backtrace.
fn print_command_result(opts: &Opts, result: Result<Option<Box<dyn Annotate>>>) -> Result<()> {
    match result {
        Ok(Some(value)) => {
            log::info!("Command result: success.");
            let profile = if atty::is(Stream::Stdout) && opts.color.unwrap_or(true) {
                ColorProfile::basic()
            } else {
                ColorProfile::default()
            };
            let doc = serde_annotate::serialize(value.as_ref())?;
            let string = match opts.format {
                Format::Json => doc.to_json().color(profile).to_string(),
                Format::Json5 => doc.to_json5().color(profile).to_string(),
                Format::HJson => doc.to_hjson().color(profile).to_string(),
                Format::Yaml => doc.to_yaml().color(profile).to_string(),
            };
            println!("{}", string);
            Ok(())
        }
        Ok(None) => {
            log::info!("Command result: success.");
            Ok(())
        }
        Err(e) => {
            log::info!("Command result: {:?}", e);
            Err(e)
        }
    }
}

// Execute is a convenience function for taking a list of strings,
// parsing them into a command, executing the command and printing the result.
fn execute<I>(args: I, opts: &Opts, transport: &TransportWrapper) -> Result<()>
where
    I: IntoIterator<Item = OsString>,
{
    let command = RootCommandHierarchy::from_iter(
        std::iter::once(OsString::from("opentitantool")).chain(args),
    );
    print_command_result(opts, command.run(opts, transport))?;
    Ok(())
}

fn main() -> Result<()> {
    let opts = parse_command_line(Opts::from_args(), args_os())?;

    let transport = backend::create(&opts.backend_opts)?;

    for command in &opts.exec {
        execute(
            shellwords::split(command)?.iter().map(OsString::from),
            &opts,
            &transport,
        )?;
    }
    print_command_result(&opts, opts.command.run(&opts, &transport))?;
    Ok(())
}
