oliver 0.1.2

Lightweight CLI mod manager for Baldur's Gate 3 on Linux
use anyhow::{bail, Result};
use larian_formats::{
    bg3::{ModuleInfoAttribute, ModuleInfoNode, Save, Version},
    lsf,
    lspk::{self, DecompressedLspk},
};
use std::{fs::File, path::PathBuf};

pub fn parse(paths: Vec<PathBuf>) -> Result<()> {
    for path in paths {
        let displayed_path = path.display().to_string();

        println!("{displayed_path}");

        for _ in displayed_path.chars() {
            print!("-");
        }

        println!();

        let file = File::open(&path)?;

        match path.extension().map(|s| s.to_string_lossy()).as_deref() {
            Some("zip") => {
                let data = lspk::entry_from_zipfile(&file)?;

                parse_lspk(&data.1)?;
            }
            Some("lsf") => {
                let data = lsf::Reader::new(file)?.read()?;
                data.print_summary();
            }
            Some("pak") => {
                let data = lspk::Reader::new(file)?.read()?;
                parse_lspk(&data)?;
            }
            _other => {
                bail!("expected .lsf or .pak file");
            }
        }

        println!();
    }

    Ok(())
}

fn parse_lspk(data: &DecompressedLspk) -> Result<()> {
    let Save { version, region } = data.extract_meta_lsx()?.extract_meta_lsx_data()?;
    let Version {
        major,
        minor,
        revision,
        build,
    } = version;

    println!("Game version : {major}.{minor}.{revision}.{build}");

    let info = region
        .node
        .children
        .node
        .iter()
        .find(|child| child.id == "ModuleInfo");

    if let Some(ModuleInfoNode { attribute, .. }) = info {
        let mut info = [("", ""), ("", ""), ("", ""), ("", "")];

        for ModuleInfoAttribute { id, value, .. } in attribute {
            if id == "Name" {
                info[0] = (id, value);
            } else if id == "Folder" {
                info[1] = (id, value);
            } else if id == "Version" || id == "Version64" {
                info[2] = (id, value);
            } else if id == "UUID" {
                info[3] = (id, value);
            }
        }

        for (id, value) in info {
            if !id.is_empty() {
                println!("{id:<13}: {value}");
            }
        }
    }

    Ok(())
}