use anyhow::Result;
use std::collections::BTreeMap;
use std::io::{BufReader, BufWriter};
use std::fs::File;
use std::path::{Path, PathBuf};
use rpfm_lib::binary::ReadBytes;
use rpfm_lib::files::{animpack::AnimPack, ContainerPath, Container, Decodeable, DecodeableExtraData, Encodeable, EncodeableExtraData};
use rpfm_lib::integrations::log::*;
use rpfm_lib::utils::last_modified_time_from_file;
use crate::config::Config;
pub fn list(config: &Config, path: &Path) -> Result<()> {
if config.verbose {
info!("Listing AnimPack Contents.");
}
let mut reader = BufReader::new(File::open(path)?);
let path_str = path.to_str().unwrap();
let mut extra_data = DecodeableExtraData::default();
extra_data.set_disk_file_path(Some(path_str));
extra_data.set_timestamp(last_modified_time_from_file(reader.get_ref())?);
extra_data.set_data_size(reader.len()?);
let pack = AnimPack::decode(&mut reader, &Some(extra_data))?;
let files: BTreeMap<_, _> = pack.files().iter().collect();
for (path, _) in files {
println!("{path}");
}
Ok(())
}
pub fn create(config: &Config, path: &Path) -> Result<()> {
if config.verbose {
info!("Creating new empty AnimPack at {}.", path.to_string_lossy());
}
let mut file = BufWriter::new(File::create(path)?);
let mut pack = AnimPack::default();
pack.encode(&mut file, &None).map_err(From::from)
}
pub fn add(config: &Config, pack_path: &Path, file_path: &[(PathBuf, String)], folder_path: &[(PathBuf, String)]) -> Result<()> {
if config.verbose {
info!("Adding files/folders to a AnimPack at {}.", pack_path.to_string_lossy());
}
let pack_path_str = pack_path.to_string_lossy().to_string();
let mut reader = BufReader::new(File::open(pack_path)?);
let mut extra_data = DecodeableExtraData::default();
extra_data.set_disk_file_path(Some(&pack_path_str));
extra_data.set_timestamp(last_modified_time_from_file(reader.get_ref())?);
extra_data.set_data_size(reader.len()?);
let mut pack = AnimPack::decode(&mut reader, &Some(extra_data))?;
for (folder_path, container_path) in folder_path {
if config.verbose {
info!("Adding folder: {container_path}");
}
pack.insert_folder(folder_path, container_path, &None, &None, false)?;
}
for (file_path, container_path) in file_path {
if config.verbose {
info!("Adding file: {container_path}");
}
pack.insert_file(file_path, container_path, &None)?;
}
pack.preload()?;
let mut writer = BufWriter::new(File::create(pack_path)?);
pack.encode(&mut writer, &None)?;
if config.verbose {
info!("Files/folders added.");
}
Ok(())
}
pub fn delete(config: &Config, pack_path: &Path, file_path: &[String], folder_path: &[String]) -> Result<()> {
if config.verbose {
info!("Delete files/folders from a AnimPack at {}.", pack_path.to_string_lossy());
}
let pack_path_str = pack_path.to_string_lossy().to_string();
let mut reader = BufReader::new(File::open(pack_path)?);
let mut extra_data = DecodeableExtraData::default();
extra_data.set_disk_file_path(Some(&pack_path_str));
extra_data.set_timestamp(last_modified_time_from_file(reader.get_ref())?);
extra_data.set_data_size(reader.len()?);
let mut pack = AnimPack::decode(&mut reader, &Some(extra_data))?;
let mut container_paths = folder_path.iter().map(|x| ContainerPath::Folder(x.to_string())).collect::<Vec<_>>();
container_paths.append(&mut file_path.iter().map(|x| ContainerPath::File(x.to_string())).collect::<Vec<_>>());
let container_paths = ContainerPath::dedup(&container_paths);
for container_path in container_paths {
if config.verbose {
info!("Deleting path: {}", container_path.path_raw());
}
pack.remove(&container_path);
}
pack.preload()?;
let mut writer = BufWriter::new(File::create(pack_path)?);
pack.encode(&mut writer, &None)?;
if config.verbose {
info!("Files/folders deleted.");
}
Ok(())
}
pub fn extract(config: &Config, pack_path: &Path, file_path: &[(String, PathBuf)], folder_path: &[(String, PathBuf)]) -> Result<()> {
if config.verbose {
info!("Extracting files/folders from a AnimPack at {}.", pack_path.to_string_lossy());
}
let pack_path_str = pack_path.to_string_lossy().to_string();
let mut reader = BufReader::new(File::open(pack_path)?);
let mut extra_data = DecodeableExtraData::default();
extra_data.set_disk_file_path(Some(&pack_path_str));
extra_data.set_timestamp(last_modified_time_from_file(reader.get_ref())?);
extra_data.set_data_size(reader.len()?);
let mut pack = AnimPack::decode(&mut reader, &Some(extra_data))?;
let mut extra_data = EncodeableExtraData::default();
if let Some(game) = &config.game {
extra_data = EncodeableExtraData::new_from_game_info(game);
}
let extra_data = Some(extra_data);
for (container_path, folder_path) in folder_path {
if config.verbose {
info!("Extracting folder: {container_path}");
}
let container_path = ContainerPath::Folder(container_path.to_owned());
pack.extract(container_path, folder_path, true, &None, false, true, &extra_data, false)?;
}
for (container_path, file_path) in file_path {
if config.verbose {
info!("Extracting file: {container_path}");
}
let container_path = ContainerPath::File(container_path.to_owned());
pack.extract(container_path, file_path, true, &None, false, true, &extra_data, false)?;
}
if config.verbose {
info!("Files/folders extracted.");
}
Ok(())
}