use crate::game_logic::game_options::{get_parameter_range, GameOptions, ONLY_FOR_CLI_PARAMETERS};
use crate::graphics::menus::retro_parameter_table::generic_logic::{
get_default_action_input, ActionInputs, CellValue, FooterData, GenericMenu, RowData,
TableParameterAction,
};
use clap::CommandFactory;
use crossterm::event::KeyCode;
use ratatui::DefaultTerminal;
pub fn setup_and_run_cli_table_parameters(
terminal: &mut DefaultTerminal,
options: &mut GameOptions,
) {
let current_preset = options.load;
let data: Vec<RowData> = load_parameter_cli_in_table(options);
let mut actions = get_default_action_input();
actions.push(ActionInputs {
key: vec![KeyCode::Char('x'), KeyCode::Char('X')],
action: vec![
TableParameterAction::ApplyAndSave(options),
TableParameterAction::Quit,
],
});
for i in 1..=7u16 {
let key_char = char::from_digit(u32::from(i), 10).unwrap();
actions.push(ActionInputs {
key: vec![
KeyCode::Char(key_char),
KeyCode::Char(key_char.to_ascii_uppercase()),
],
action: vec![TableParameterAction::LoadPreset(i, |preset| {
let footer_updated_data = Some(parameters_cli_get_footer_data(Some(preset)));
if let Ok(game_options_from_preset) =
&mut GameOptions::load_from_toml_preset(preset)
{
(
Some(load_parameter_cli_in_table(game_options_from_preset)),
footer_updated_data,
)
} else {
(None, footer_updated_data)
}
})],
});
}
GenericMenu::new(
data,
¶meters_cli_get_headers(),
parameters_cli_get_footer_data(current_preset),
current_preset,
)
.run(actions, terminal);
}
#[must_use]
fn load_parameter_cli_in_table(options: &mut GameOptions) -> Vec<RowData> {
let cmd = GameOptions::command();
let mut rows = vec![];
let mut arg_value;
for arg in cmd.get_arguments().filter(|arg| {
!ONLY_FOR_CLI_PARAMETERS
.iter()
.any(|arg_pattern| arg.get_long().unwrap().contains(arg_pattern))
}) {
let mut all_value_for_this_arg = vec![];
let pv_bool_enum = arg.get_possible_values();
if pv_bool_enum.is_empty() {
if let Some(range) = get_parameter_range(arg.get_long().unwrap()) {
all_value_for_this_arg.extend(range.map(|i| i.to_string()));
} else {
all_value_for_this_arg.extend(GameOptions::emojis_iterator());
add_unique_symbol(&mut all_value_for_this_arg, options.head_symbol.clone());
add_unique_symbol(&mut all_value_for_this_arg, options.body_symbol.clone());
}
} else {
all_value_for_this_arg
.extend(pv_bool_enum.into_iter().map(|v| v.get_name().to_string()));
}
let mut index = 0;
if let Some(default_value) = options
.to_structured_toml()
.get(&arg.get_long().unwrap().replace('-', "_"))
{
let mut default_str = default_value.to_string();
if default_str.contains('"') {
default_str = default_str.split('"').collect::<Vec<&str>>()[1].to_string();
}
index = all_value_for_this_arg
.iter()
.position(|v| v.eq_ignore_ascii_case(&default_str))
.unwrap_or(0);
}
let arg_name = "--".to_string() + arg.get_long().unwrap();
arg_value = CellValue::new_with_options(arg_name, all_value_for_this_arg, index);
rows.push(RowData::new(vec![
arg_value,
CellValue::new(arg.get_long().unwrap().to_string()),
CellValue::new(
arg.get_help()
.unwrap_or_else(|| {
panic!("Missing help for argument: {}", arg.get_long().unwrap())
})
.to_string(),
),
]));
}
rows
}
#[must_use]
fn parameters_cli_get_headers() -> Vec<String> {
vec![
"🎯 Value".to_string(),
"📋 Parameter".to_string(),
"📝 Description / super power".to_string(),
]
}
#[must_use]
pub fn parameters_cli_get_footer_data(current_preset: Option<u16>) -> Vec<FooterData> {
vec![
FooterData {
symbol: "Esc".into(),
text: "Quit".into(),
value: None,
},
FooterData {
symbol: "x".into(),
text: "Quit & Save".into(),
value: None,
},
FooterData {
symbol: "↕".into(),
text: "Move".into(),
value: None,
},
FooterData {
symbol: "← →".into(),
text: "Change value".into(),
value: None,
},
FooterData {
symbol: "1-7".into(),
text: "Load".into(),
value: current_preset,
},
]
}
fn add_unique_symbol(collection: &mut Vec<String>, symbol: String) {
if !collection.contains(&symbol) {
collection.push(symbol);
}
}