use std::{fmt::Debug, sync::Arc};
use crate::{
error::{Error, ErrorValue, Result},
file,
utility::{OptionCache, OptionCacheExt},
Ironworks,
};
use super::{borrowed::Borrowed, mapper::Mapper, metadata::SheetMetadata, sheet::Sheet};
#[derive(Debug, Default)]
pub struct ExcelOptions {
pub(super) language: Option<u8>,
}
impl<'i> ExcelOptions {
pub fn language(&mut self, language: impl Into<u8>) -> &mut Self {
self.language = Some(language.into());
self
}
pub fn build(
&self,
ironworks: impl Into<Borrowed<'i, Ironworks>>,
mapper: impl Mapper + 'static,
) -> Excel<'i> {
Excel::with_options(ironworks, mapper, self)
}
}
pub struct Excel<'i> {
default_language: u8,
ironworks: Borrowed<'i, Ironworks>,
mapper: Box<dyn Mapper>,
list: OptionCache<file::exl::ExcelList>,
}
impl Debug for Excel<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Excel")
.field("default_language", &self.default_language)
.finish()
}
}
impl<'i> Excel<'i> {
pub fn new(
ironworks: impl Into<Borrowed<'i, Ironworks>>,
mapper: impl Mapper + 'static,
) -> Self {
Self::with().build(ironworks, mapper)
}
pub fn with() -> ExcelOptions {
Default::default()
}
fn with_options(
ironworks: impl Into<Borrowed<'i, Ironworks>>,
mapper: impl Mapper + 'static,
options: &ExcelOptions,
) -> Self {
Self {
default_language: options.language.unwrap_or(0),
ironworks: ironworks.into(),
mapper: Box::new(mapper),
list: Default::default(),
}
}
pub fn version(&self) -> Result<String> {
self.ironworks.version(&self.mapper.exl())
}
pub fn list(&self) -> Result<Arc<file::exl::ExcelList>> {
self.list
.try_get_or_insert(|| self.ironworks.file(&self.mapper.exl()))
}
pub fn sheet<S: SheetMetadata>(&self, sheet_metadata: S) -> Result<Sheet<S>> {
let sheet_name = sheet_metadata.name();
let list = self.list()?;
if !list.has(&sheet_name) {
return Err(Error::NotFound(ErrorValue::Sheet(sheet_name)));
}
Ok(Sheet::new(
sheet_metadata,
self.default_language,
self.ironworks.clone(),
self.mapper.as_ref(),
))
}
}