use std::{path::PathBuf, sync::Arc};
use minijinja::{State, Value, value::Object};
use taganak_core::graphs::Graph;
use taganak_orm::{GraphORM, GraphORMMeta};
use tokio::runtime::Handle;
use tracing::debug;
use crate::{
Params,
res::str_to_term,
site::{Asset, Page},
};
#[derive(Debug, Clone)]
pub struct RdfAssetFn<G> {
params: Params<'static, G>,
page: GraphORMMeta<Page>,
}
impl<G> RdfAssetFn<G>
where
G: Graph + std::fmt::Debug + Sync + 'static,
{
pub fn new(params: Params<'static, G>, page: GraphORMMeta<Page>) -> Self {
Self { params, page }
}
}
impl<G> Object for RdfAssetFn<G>
where
G: Graph + std::fmt::Debug + Sync + 'static,
{
fn call(
self: &Arc<Self>,
_state: &State<'_, '_>,
args: &[Value],
) -> Result<Value, minijinja::Error> {
if args.is_empty() {
return Err(minijinja::Error::new(
minijinja::ErrorKind::MissingArgument,
"needs subject",
));
}
if args.len() > 1 {
return Err(minijinja::Error::new(
minijinja::ErrorKind::TooManyArguments,
"too many arguments",
));
}
let handle = Handle::current();
let term_str = args[0].to_string();
handle.block_on(async {
let asset_subject = str_to_term(
self.params.clone().base(Some(self.page.subject().unwrap())),
&term_str,
)
.unwrap();
debug!(
"Finding asset {} relative to page {}",
asset_subject,
self.page.subject().unwrap()
);
let page_iri = self.page.subject().unwrap().to_iri().unwrap().clone();
let graph_clone = self.params.graph.clone();
let graph = graph_clone.read().unwrap();
let view = graph.view().await;
let asset = Asset::deserialize(view.clone(), &asset_subject)
.await
.unwrap()
.into_deref();
let out_rel = match asset.output {
Some(output) => {
let page_path = match &self.page.output {
None => PathBuf::from(
page_iri
.relative_to(&self.params.base.as_ref().unwrap().to_iri().unwrap())
.to_string(),
),
Some(output) => PathBuf::from(output),
};
let output_path = PathBuf::from(output.clone());
debug!(
?page_path,
?output_path,
"Asset has explicit output path, calculating relative to page output path"
);
let mut out_rel = PathBuf::new();
for (n, _) in page_path.components().enumerate() {
if n > 0 {
out_rel.push("..");
}
}
out_rel.push(output_path);
out_rel
}
None => {
debug!(
?page_iri,
?asset_subject,
"Calculating asset path relative to page"
);
PathBuf::from(
asset_subject
.to_iri()
.unwrap()
.relative_to(&page_iri)
.to_string(),
)
}
};
Ok(Value::from(out_rel.to_str().unwrap().to_string()))
})
}
}