extern crate crossterm;

use crossterm::style::{
    Colorize,
    Styler
};

use super::{
    Evolver,
    evol::LOG_FILENAME
};

impl Evolver {
    /// Lists available commands or shows usage of a command.
    pub fn help(&self, command: &str) {
        match command {
            "" => {
                println!("{:32}{}", "exit | quit | end | bye | q", "The end of the show".green());
                println!("{:32}{}", "help | ?", "List available commands".green());
                println!("{:32}{}", "help | ? <command>", "Learn more about a command".green());
                println!("{:32}{}", "stat", "Show statistics".green());
                println!("{:32}{}", "evol | e", "Evolve population".green());
                println!("{:32}{}", "par | p", "Change evolution parameter".green());
                println!("{:32}{}", "arch | a", "Change boolnet architecture. Warning: may drop current population".green());
                println!("{:32}{}", "pop", "Change population size".green());
                println!("{:32}{}", "reset", "Reset population. Warning: drops current one".green());
                println!("{:32}{}", "bitran | b", "Change bitransform or show available ones".green());
                println!("{:32}{}", "run | r", "Run boolnet with input, print output".green());
                println!("{:32}{}", "save", "Save evolver to dir".green());
                println!("{:32}{}", "load", "Load evolver from dir. Warning: drops current evolver".green());
                println!("{:32}{}", "set | s", "Change setting".green());
                println!("{:32}{}", "about", "Show general description, disclaimer etc.".green());
            },
            "evol" | "e" => {
                println!("{:32}{}", "evol", "Evolve population until any key is pressed".green());
                println!("{:32}{}{}{}{}{}", "evol <num>", "Evolve population for ".green(), "num".bold(), " epochs. If ".green(), "num".bold(), " is 0, same as \"evol\"".green());
            }
            "par" | "p" => {
                println!("{:32}{}{}{}{}{}", "par <parameter> <value>", "Set ".green(), "parameter".bold(), " to ".green(), "value".bold(), ". Value must be admissible".green());
            },
            "arch" | "a" => {
                println!("{:48}{}", "arch <height> <size> <rands> <layers> <cycles>", "New boolnet architecture with".green());
                println!("{:48}{}{}", "", "height".bold(), ": height of each boolon's input tree".green());
                println!("{:48}{}{}", "", "size".bold(), ": boolons in each layer".green());
                println!("{:48}{}{}", "", "rands".bold(), ": extra random-output-boolons in each layer".green());
                println!("{:48}{}{}", "", "layers".bold(), ": number of layers".green());
                println!("{:48}{}{}", "", "cycles".bold(), ": repeats of propagation through all layers".green());
                println!("{:48}{}", "", "Warning: drops current population if anything other than cycles changes".green());
            },
            "pop" => {
                println!("{:32}{}{}", "pop <size>", "Change population size to ".green(), "size".bold());
                println!("{:32}{}", "", "Decrease: remove boolnets with lowest scores".green());
                println!("{:32}{}", "", "Increase: add inheritants of existing boolnets and evolve for 1 epoch".green());
            },
            "reset" => {
                println!("{:32}{}", "reset", "Reinitialize all boolnets randomly".green());
                println!("{:32}{}", "", "Warning: drops current population".green());
            },
            "bitran" | "b" => {
                println!("{:48}{}", "bitran", "Show available bitransforms and their preferences".green());
                println!("{:48}{}{}{}{}{}{}", "bitran <id> [pref1 [pref2 ...[prefN]...]]", "Change bitransform to ".green(), "id".bold(), " with preferences ".green(), "pref1".bold(), ", ..., ".green(), "prefN".bold());
                println!("{:48}{}", "", "Preferences must be unsigned integers".green());
                println!("{:48}{}", "", "All boolnets of population become unscored".green());
            },
            "run" | "r" => {
                println!("{:32}{}{}{}{}{}", "run <index> <hex-string>", "Run ".green(), "index".bold(), "-th boolnet (by score, descending) with ".green(), "hex-string".bold(), " input (bytes) and print its output".green());
            },
            "save" => {
                println!("{:32}{}{}{}", "save <dirpath>", "Save evolver to dir specified by ".green(), "dirpath".bold(), " (cannot start with \"/\")".green());
            },
            "load" => {
                println!("{:32}{}{}", "load <dirpath>", "Load evolver from dir specified by ".green(), "dirpath".bold());
                println!("{:32}{}", "", "Warning: drops current evolver".green());
            },
            "set" | "s" => {
                println!("{:32}{}{}{}", "set log off|on", "Turn off/on logging to ".green(), LOG_FILENAME.cyan(), " while evolving".green());
                println!("{:32}{}", "set test new|all", "At each epoch test only new boolnets or all".green());
                println!("{:32}{}", "set print improve|all", "Print (and log) epochs when max score improved or all epochs".green());
            },
            _ => {
                println!("{}", "No help on this command".dark_yellow().bold());
            }
        }
    }

}
