use crate::common::read_current_installed_mods;
use anyhow::Result;
use std::collections::HashMap;
pub fn list(order: bool, app_data_path: &str) -> Result<()> {
let parsed_settings = read_current_installed_mods(app_data_path)?;
let all_mods = parsed_settings
.find_node_by_id("Mods")?
.children
.first()
.into_iter()
.flat_map(|c| {
c.node.iter().filter_map(|n| {
let mut info = [""; 3];
for attr in &n.attribute {
match attr.id.as_str() {
"Name" => info[0] = &attr.value,
"Folder" => info[1] = &attr.value,
"UUID" => info[2] = &attr.value,
_anything_else => {}
}
}
if info.iter().any(|s| s.is_empty()) {
None
} else {
Some(info)
}
})
});
if order {
let nodes = parsed_settings
.find_node_by_id("ModOrder")?
.children
.first();
let order_length = nodes.as_ref().map_or(0, |c| c.node.len());
let ordered_uuids = nodes.into_iter().flat_map(|c| {
c.node
.iter()
.filter_map(|n| n.attribute.first().map(|a| a.value.as_str()))
});
print_ordered_mods(order_length, ordered_uuids, all_mods);
} else {
print_unordered_mods(all_mods);
}
Ok(())
}
fn print_unordered_mods<'a>(mods: impl Iterator<Item = [&'a str; 3]>) {
for [name, _, uuid] in mods {
println!("{uuid}: {name}");
}
}
fn print_ordered_mods<'a>(
order_length: usize,
ordered_uuids: impl Iterator<Item = &'a str>,
all_mods: impl Iterator<Item = [&'a str; 3]>,
) {
let mut uuid_indexed_mods: HashMap<_, _> =
all_mods.map(|[name, _, uuid]| (uuid, name)).collect();
let padding = order_length
.checked_ilog10()
.and_then(|i| usize::try_from(i + 1).ok())
.unwrap_or_default();
println!("Load order used by game:");
for (i, uuid) in ordered_uuids.enumerate() {
let name = uuid_indexed_mods.remove(uuid).unwrap_or("<mod not found>");
println!("{i:>padding$}. {uuid}: {name}");
}
if uuid_indexed_mods.is_empty() {
return;
}
println!("\nMods not present in load order:");
for (uuid, name) in uuid_indexed_mods {
println!("?. {uuid} {name}");
}
}