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