use crate::settings::Settings;
use anyhow::Result;
use larian_formats::{bg3::ModuleInfo, lspk::Lspk};
use std::path::PathBuf;

impl Settings {
    pub(crate) fn dump_helper(path: PathBuf) -> Result<()> {
        parse_inner(std::iter::once(path), Style::Dump)
    }

    pub(crate) fn parse_helper(
        paths: impl IntoIterator<Item = PathBuf>,
        verbose: bool,
    ) -> Result<()> {
        let style = if verbose {
            Style::Verbose
        } else {
            Style::Basic
        };

        parse_inner(paths, style)
    }
}

#[derive(Debug, Clone, Copy)]
enum Style {
    Basic,
    Dump,
    Verbose,
}

impl Style {
    const fn is_print(self) -> bool {
        matches!(self, Self::Basic | Self::Verbose)
    }
}

fn parse_inner(paths: impl IntoIterator<Item = PathBuf>, style: Style) -> Result<()> {
    for path in paths {
        if style.is_print() {
            let displayed_path = path.display().to_string();

            println!("{displayed_path}");

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

            println!();
        }

        let data = Lspk::from_file(path)?;

        print_lspk(data, style)?;

        if style.is_print() {
            println!();
        }
    }

    Ok(())
}

fn print_lspk(data: Lspk, style: Style) -> Result<()> {
    let meta_lsx = data.deserialize_meta_lsx()?;

    if !style.is_print() {
        println!("{}", String::from_utf8_lossy(&data.packed_bytes));
        return Ok(());
    }

    let ModuleInfo {
        author,
        description,
        folder,
        md5,
        name,
        num_players,
        module_type,
        uuid,
        version,
        ..
    } = meta_lsx.module_info;

    println!("Name         : {name}");
    println!("Folder       : {folder}");
    println!("Version64    : {version}");
    println!("UUID         : {uuid}");

    if !matches!(style, Style::Verbose) {
        return Ok(());
    }

    println!("Author       : {author}");
    println!("Description  : {description}");
    println!("MD5          : {md5}");
    println!("NumPlayers    : {num_players}");
    println!("Type         : {module_type}");

    Ok(())
}
