// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Provides support for registering and handling commands as well as displaying the command line
// help.

use std::collections::HashMap;
use std::fmt::{self, Display};
use std::io::Write;
use std::process::Child;

use remain::sorted;

const INDENT: &str = "  ";

#[sorted]
pub enum Error {
    CommandInvalidArguments(String),
    CommandNotFound(String),
    CommandNotImplemented(String),
    CommandReturnedError,
    DuplicateCommand(Vec<String>),
    FlagFilter,
}

impl Display for Error {
    #[remain::check]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        #[sorted]
        match self {
            CommandInvalidArguments(msg) => write!(f, "invalid arguments: {}", msg),
            CommandNotFound(command) => write!(f, "unknown command: {}", command),
            CommandNotImplemented(command) => write!(f, "command not implemented: {}", command),
            CommandReturnedError => write!(f, "command failed"),
            DuplicateCommand(dups) => write!(f, "duplicate commands: {}", dups.join(", ")),
            FlagFilter => write!(f, "error filtering flags"),
        }
    }
}

pub fn wait_for_result(mut child: Child) -> Result<(), Error> {
    match child.wait() {
        Ok(status) => {
            if status.success() {
                Ok(())
            } else {
                Err(Error::CommandReturnedError)
            }
        }
        Err(_) => Err(Error::CommandReturnedError),
    }
}

// Keeps all the state required to interpret a dispatched command, and provides interfaces for:
// * Registering commands (along with strings required to generate help text).
// * Dispatching an issued command.
// * Providing token completion given partial input.
pub struct Dispatcher {
    registered_commands: Vec<Command>,
}

impl Dispatcher {
    pub fn new() -> Dispatcher {
        Dispatcher {
            registered_commands: Vec::new(),
        }
    }

    // Register a command description that can be handled by the dispatcher.
    pub fn register_command(&mut self, cmd: Command) -> &mut Dispatcher {
        self.registered_commands.push(cmd);
        self
    }

    // Lookup a command by name.
    pub fn find_by_name(&self, name: &str) -> Option<&Command> {
        find_by_name(name, &self.registered_commands)
    }

    // Return a CompletionResult that represents auto-completion suggestions for |tokens|.
    pub fn complete_command(&self, tokens: Vec<String>) -> CompletionResult {
        if tokens.is_empty() {
            return complete_by_name("", &self.registered_commands);
        }

        let (commands, entry) = self.get_command_list(tokens);

        if commands.is_empty() {
            if entry.tokens.len() == 1 {
                return complete_by_name(&entry.tokens[0], &self.registered_commands);
            }
            return CompletionResult::NoMatches;
        }

        let command: &Command = commands.last().unwrap();
        if let Some(cb) = command.completion_callback {
            return (cb)(&entry);
        }

        CompletionResult::NoMatches
    }

    // Execute the command handler represented by |tokens|. Flags will be parsed and flag handling
    // callbacks will be invoked.
    pub fn handle_command(&self, tokens: Vec<String>) -> Result<(), Error> {
        if tokens.is_empty() {
            return Err(Error::CommandNotFound(tokens.join(" ")));
        }

        let mut command: &Command = self
            .find_by_name(&tokens[0])
            .ok_or_else(|| Error::CommandNotFound(tokens[0].to_string()))?;

        let mut flag_callbacks: Vec<CommandCallback> = Vec::new();
        let entry = &mut Arguments {
            tokens,
            position: 1,
            flags: HashMap::new(),
        };

        if let Some(cb) = command.flag_callback {
            flag_callbacks.push(cb);
        }
        while entry.position < entry.tokens.len() {
            let sub: Option<&Command> = command.handle_tokens(entry);

            if sub.is_none() {
                break;
            }
            entry.position += 1;
            command = sub.unwrap();
            if let Some(cb) = command.flag_callback {
                flag_callbacks.push(cb);
            }
        }
        if command.command_callback.is_none() {
            return Err(Error::CommandNotImplemented(entry.get_command().join(" ")));
        }

        for cb in flag_callbacks {
            (cb)(&command, entry)?;
        }
        (command.command_callback.unwrap())(&command, entry)
    }

    pub fn validate(&mut self) -> Result<(), Error> {
        self.registered_commands
            .sort_unstable_by(|a: &Command, b: &Command| a.name.cmp(&b.name));

        let mut duplicates: Vec<String> = Vec::new();
        for i in 1..self.registered_commands.len() {
            let name = &self.registered_commands[i - 1].name;
            if name == &self.registered_commands[i].name {
                duplicates.push(name.to_string());
            }
        }

        if !duplicates.is_empty() {
            return Err(Error::DuplicateCommand(duplicates));
        }
        Ok(())
    }

    // Generate and return the help string.
    pub fn help_string(&self, w: &mut dyn Write, opt_cmds: Option<&[&str]>) -> Result<(), Error> {
        match opt_cmds {
            Some(cmds) => {
                for name in cmds {
                    if let Some(cmd) = self.find_by_name(name) {
                        cmd.append_help_string(w, 0);
                    } else {
                        return Err(Error::CommandNotFound(name.to_string()));
                    }
                }
            }
            None => {
                for c in &self.registered_commands {
                    c.append_help_string(w, 0);
                }
            }
        }
        Ok(())
    }

    fn get_command_list(&self, tokens: Vec<String>) -> (Vec<&Command>, Arguments) {
        let mut list: Vec<&Command> = Vec::new();
        let mut entry = Arguments::new();
        if tokens.is_empty() {
            return (list, entry);
        }
        entry.tokens = tokens;

        let c = self.find_by_name(&entry.tokens[0]);
        if c.is_none() {
            return (list, entry);
        }

        entry.position = 1;
        let mut command: &Command = c.unwrap();
        list.push(command);
        while entry.position < entry.tokens.len() {
            let sub: Option<&Command> = command.handle_tokens(&mut entry);

            if sub.is_none() {
                break;
            }
            entry.position += 1;
            command = sub.unwrap();
            list.push(command);
        }
        (list, entry)
    }
}

// Owns the data required to identify the command, and serves as a node in a tree. Sub commands can
// be registered. It contains callbacks for the following:
// * flag/switch processing
// * executing the command
// * providing command completion suggestions.
pub struct Command {
    name: String,
    usage: String,
    description: String,
    sub_commands: Vec<Command>,
    flags: Vec<Flag>,
    flag_callback: Option<CommandCallback>,
    command_callback: Option<CommandCallback>,
    completion_callback: Option<CompletionCallback>,
    help_callback: HelpCallback,
}

impl Command {
    pub fn new(name: String, usage: String, description: String) -> Command {
        Command {
            name,
            usage,
            description,
            sub_commands: Vec::new(),
            flags: Vec::new(),
            flag_callback: None,
            command_callback: None,
            completion_callback: None,
            help_callback: default_help_callback,
        }
    }

    // Set the callback that is executed when this command or a sub command is invoked primarily for
    // the purpose of filtering or handling flags.
    pub fn set_flag_callback(mut self, replacement: Option<CommandCallback>) -> Command {
        self.flag_callback = replacement;
        self
    }

    // Set the callback that is executed when this command invoked directly.
    pub fn set_command_callback(mut self, replacement: Option<CommandCallback>) -> Command {
        self.command_callback = replacement;
        self
    }

    // Set the callback to handle command completion for arguments of this command.
    pub fn set_completion_callback(mut self, replacement: Option<CompletionCallback>) -> Command {
        self.completion_callback = replacement;
        self
    }

    // Set the callback to handle command completion for arguments of this command.
    pub fn set_help_callback(mut self, replacement: HelpCallback) -> Command {
        self.help_callback = replacement;
        self
    }

    pub fn register_subcommand(mut self, cmd: Command) -> Command {
        self.sub_commands.push(cmd);
        self
    }

    pub fn register_flag(mut self, flag: Flag) -> Command {
        self.flags.push(flag);
        self
    }

    pub fn get_name(&self) -> &str {
        &self.name
    }

    pub fn append_help_string(&self, w: &mut dyn Write, level: usize) {
        (self.help_callback)(self, w, level);
    }

    fn find_flag(&self, flag: &str) -> Option<&Flag> {
        for f in &self.flags {
            if f.name == flag {
                return Some(&f);
            }
        }
        None
    }

    fn find_subcommand(&self, name: &str) -> Option<&Command> {
        find_by_name(name, &self.sub_commands)
    }

    fn handle_tokens(&self, entry: &mut Arguments) -> Option<&Command> {
        while entry.position < entry.tokens.len() {
            let token = &entry.tokens[entry.position];

            let result = self.find_subcommand(token);
            if result.is_some() {
                return result;
            }

            let mut parts = token.splitn(2, '=');
            let name = parts.next().unwrap().to_string();
            let flag = self.find_flag(&name)?;

            let value = flag.get_default_value().parse(parts.next().unwrap_or(""));
            if value.is_none() {
                panic!();
            }
            entry.flags.insert(name, value.unwrap());

            entry.position += 1;
        }
        None
    }
}

pub fn default_help_callback(cmd: &Command, w: &mut dyn Write, level: usize) {
    let mut prefix = INDENT.repeat(level);
    write!(w, "{}{}", &prefix, &cmd.name).unwrap();
    prefix.push_str(&INDENT);
    if !cmd.usage.is_empty() {
        write!(w, " {}", &cmd.usage).unwrap();
    }
    writeln!(w).unwrap();

    if !cmd.description.is_empty() {
        writeln!(w, "{}{}", &prefix, &cmd.description).unwrap();
    }

    if !cmd.flags.is_empty() {
        if !cmd.description.is_empty() {
            writeln!(w).unwrap();
        }
        write!(w, "{}Options:", &prefix).unwrap();
        for flag in &cmd.flags {
            writeln!(w).unwrap();
            flag.append_help_string(w, level + 2);
        }
    }

    if !cmd.sub_commands.is_empty() {
        if !cmd.description.is_empty() || !cmd.flags.is_empty() {
            writeln!(w).unwrap();
        }
        writeln!(w, "{}Subcommands:", &prefix).unwrap();
        for sub in &cmd.sub_commands {
            sub.append_help_string(w, level + 2);
        }
    } else {
        writeln!(w).unwrap();
    }
}

impl HasName for Command {
    fn get_name(&self) -> &str {
        &self.name
    }
}

pub struct Arguments {
    tokens: Vec<String>,
    position: usize,
    flags: HashMap<String, FlagType>,
}

impl Arguments {
    fn new() -> Arguments {
        Arguments {
            tokens: Vec::new(),
            position: 0,
            flags: HashMap::new(),
        }
    }

    pub fn get_command(&self) -> &[String] {
        &self.tokens[0..self.position]
    }

    pub fn get_tokens(&self) -> &[String] {
        &self.tokens
    }

    pub fn get_flag(&self, flag: &str) -> Option<&FlagType> {
        self.flags.get(flag)
    }

    pub fn get_args(&self) -> &[String] {
        &self.tokens[self.position..]
    }
}

pub enum CompletionResult {
    NoMatches,
    SingleDiff(String),
    WholeTokenList(Vec<String>),
}

type CommandCallback = fn(cmd: &Command, args: &Arguments) -> Result<(), Error>;
type CompletionCallback = fn(args: &Arguments) -> CompletionResult;
type HelpCallback = fn(cmd: &Command, w: &mut dyn Write, level: usize);

pub enum FlagType {
    NoValue,
    Boolean(bool),
    Integer(i64),
    Float(f64),
    String(String),
}

impl FlagType {
    pub fn parse(&self, s: &str) -> Option<FlagType> {
        match self {
            FlagType::NoValue => Some(FlagType::NoValue),
            FlagType::Boolean(_) => match s.parse::<bool>() {
                Ok(b) => Some(FlagType::Boolean(b)),
                Err(_) => None,
            },
            FlagType::Integer(_) => match s.parse::<i64>() {
                Ok(i) => Some(FlagType::Integer(i)),
                Err(_) => None,
            },
            FlagType::Float(_) => match s.parse::<f64>() {
                Ok(f) => Some(FlagType::Float(f)),
                Err(_) => None,
            },
            FlagType::String(_) => Some(FlagType::String(s.to_string())),
        }
    }
}

pub struct Flag {
    name: String,
    description: String,
    default_value: FlagType,
}

impl HasName for Flag {
    fn get_name(&self) -> &str {
        &self.name
    }
}

impl Flag {
    pub fn new(name: String, description: String, default_value: FlagType) -> Flag {
        Flag {
            name,
            description,
            default_value,
        }
    }

    pub fn append_help_string(&self, w: &mut dyn Write, level: usize) {
        let prefix = INDENT.repeat(level);
        write!(w, "{}{}", &prefix, &self.name).unwrap();
        let value_cb = |w: &mut dyn Write, value: String| {
            write!(w, "{}{}{}", &value, &prefix, INDENT).unwrap();
        };
        match &self.default_value {
            FlagType::NoValue => {
                write!(w, " ").unwrap();
            }
            FlagType::Boolean(default) => {
                value_cb(w, format!("=[true|false]  default: {}\n", default));
            }
            FlagType::Integer(default) => {
                value_cb(w, format!("=<int>  default: {}\n", default));
            }
            FlagType::Float(default) => {
                value_cb(w, format!("=<float>  default: {}\n", default));
            }
            FlagType::String(default) => {
                value_cb(w, format!("=<value>  default: {}\n", default));
            }
        }
        writeln!(w, "{}", &self.description).unwrap();
    }

    pub fn get_default_value(&self) -> &FlagType {
        &self.default_value
    }
}

// Internal trait used to share logic used to walk lists of Commands and Flags.
trait HasName {
    fn get_name(&self) -> &str;
}

// Fetch a reference to an entry in a list by matching against get_name().
fn find_by_name<'a, T: HasName>(name: &str, list: &'a [T]) -> Option<&'a T> {
    for c in list {
        if *c.get_name() == *name {
            return Some(c);
        }
    }
    None
}

// Provide a CompletionResult after prefix matching against get_name().
fn complete_by_name<T: HasName>(name: &str, list: &[T]) -> CompletionResult {
    let mut suggestions: Vec<String> = Vec::new();
    for c in list {
        if c.get_name().starts_with(name) {
            suggestions.push(c.get_name().to_string());
        }
    }
    if suggestions.is_empty() {
        CompletionResult::NoMatches
    } else if suggestions.len() == 1 {
        CompletionResult::SingleDiff(suggestions[0][name.len()..].to_string())
    } else {
        CompletionResult::WholeTokenList(suggestions)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use std::str;

    static PARENT_COMMAND_NAME: &str = "test";
    static CHILD_COMMAND_NAME: &str = "subtest";

    fn flag_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        Ok(())
    }

    fn false_flag_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        Err(Error::FlagFilter)
    }

    fn panic_flag_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        panic!()
    }

    fn command_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        Ok(())
    }

    fn false_command_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        Err(Error::CommandReturnedError)
    }

    fn panic_command_callback(_cmd: &Command, _args: &Arguments) -> Result<(), Error> {
        panic!()
    }

    fn completion_callback(_args: &Arguments) -> CompletionResult {
        CompletionResult::NoMatches
    }

    fn panic_completion_callback(_args: &Arguments) -> CompletionResult {
        panic!()
    }

    fn default_dispatcher(parent: Command) -> Dispatcher {
        let mut dispatcher = Dispatcher::new();
        dispatcher.register_command(parent);
        dispatcher
    }

    fn default_command(name: String, usage: String, description: String) -> Command {
        Command::new(name, usage, description)
            .set_flag_callback(Some(panic_flag_callback))
            .set_command_callback(Some(panic_command_callback))
            .set_completion_callback(Some(panic_completion_callback))
    }

    fn default_parent_command(child: Command) -> Command {
        default_command(
            PARENT_COMMAND_NAME.to_string(),
            format!("[{}]", CHILD_COMMAND_NAME),
            "parent test command.".to_string(),
        )
        .register_subcommand(child)
    }

    fn default_child_command() -> Command {
        default_command(
            CHILD_COMMAND_NAME.to_string(),
            "".to_string(),
            "parent test command.".to_string(),
        )
    }

    #[test]
    fn test_handle_command_empty() {
        let dispatcher = default_dispatcher(default_parent_command(default_child_command()));

        let mut tokens: Vec<String> = Vec::new();
        tokens.push(PARENT_COMMAND_NAME.to_string());

        assert!(!dispatcher.handle_command(Vec::new()).is_ok());
    }

    #[test]
    fn test_handle_command_parent() {
        let dispatcher = default_dispatcher(
            default_parent_command(default_child_command().set_flag_callback(Some(flag_callback)))
                .set_flag_callback(Some(flag_callback))
                .set_command_callback(Some(command_callback)),
        );

        let mut tokens: Vec<String> = Vec::new();
        tokens.push(PARENT_COMMAND_NAME.to_string());

        assert!(dispatcher.handle_command(tokens).is_ok());
    }

    #[test]
    fn test_handle_command_child() {
        let dispatcher = default_dispatcher(
            default_parent_command(
                default_child_command()
                    .set_flag_callback(Some(flag_callback))
                    .set_command_callback(Some(command_callback)),
            )
            .set_flag_callback(Some(flag_callback)),
        );

        let mut tokens: Vec<String> = Vec::new();
        tokens.push(PARENT_COMMAND_NAME.to_string());
        tokens.push(CHILD_COMMAND_NAME.to_string());

        assert!(dispatcher.handle_command(tokens).is_ok());
    }

    #[test]
    fn test_handle_command_false_flag_callback() {
        let dispatcher = default_dispatcher(
            default_parent_command(default_child_command())
                .set_flag_callback(Some(false_flag_callback)),
        );

        let mut tokens: Vec<String> = Vec::new();
        tokens.push(PARENT_COMMAND_NAME.to_string());
        tokens.push(CHILD_COMMAND_NAME.to_string());

        assert!(!dispatcher.handle_command(tokens).is_ok());
    }

    #[test]
    fn test_help_string() {
        let dispatcher = default_dispatcher(
            default_command("1".to_string(), "2".to_string(), "3".to_string())
                .register_subcommand(default_command(
                    "4".to_string(),
                    "5".to_string(),
                    "6".to_string(),
                ))
                .register_subcommand(
                    default_command("7".to_string(), "".to_string(), "".to_string())
                        .register_subcommand(
                            default_command("8".to_string(), "9".to_string(), "10".to_string())
                                .register_flag(Flag::new(
                                    "11".to_string(),
                                    "12".to_string(),
                                    FlagType::Integer(0),
                                )),
                        ),
                ),
        );

        let mut result: Vec<u8> = Vec::new();
        assert!(dispatcher
            .help_string(&mut result, Some(&["not a command"]))
            .is_err());
        assert!(dispatcher.help_string(&mut result, None).is_ok());
        assert_eq!(
            str::from_utf8(&result).unwrap(),
            r#"1 2
  3

  Subcommands:
    4 5
      6

    7
      Subcommands:
        8 9
          10

          Options:
            11=<int>  default: 0
              12

"#
        );
    }
}
