use crate::error::JournalError;
use std::path::Path;
use tera::{Context, Tera};

const NEW_ENTRY: &str = r#"[[!meta title="{{ title }}"]]
[[!meta date="{{ date }}"]]
{% for topic in topics %}
[[!meta link="{{ topic }}"]]
{% endfor %}

"#;

const NEW_TOPIC: &str = r#"[[!meta title="{{ title }}"]]

Describe the topic here.

# Entries

[[!inline pages="link(.)" archive=yes reverse=yes trail=yes]]
"#;

pub struct Templates {
    tera: Tera,
}

impl Templates {
    pub fn new(dirname: &Path) -> Result<Self, JournalError> {
        let glob = format!("{}/.config/templates/*", dirname.display());
        let mut tera = Tera::new(&glob).unwrap_or_default();
        add_default_template(&mut tera, "new_entry", NEW_ENTRY);
        add_default_template(&mut tera, "new_topic", NEW_TOPIC);
        Ok(Self { tera })
    }

    pub fn new_draft(&self, context: &Context) -> Result<String, JournalError> {
        self.render("new_entry", context)
    }

    pub fn new_topic(&self, context: &Context) -> Result<String, JournalError> {
        self.render("new_topic", context)
    }

    fn render(&self, name: &str, context: &Context) -> Result<String, JournalError> {
        match self.tera.render(name, context) {
            Ok(s) => Ok(s),
            Err(e) => match e.kind {
                tera::ErrorKind::TemplateNotFound(x) => Err(JournalError::TemplateNotFound(x)),
                _ => Err(JournalError::TemplateRender(name.to_string(), e)),
            },
        }
    }
}

fn add_default_template(tera: &mut Tera, name: &str, template: &str) {
    let context = Context::new();
    if let Err(err) = tera.render(name, &context) {
        if let tera::ErrorKind::TemplateNotFound(_) = err.kind {
            tera.add_raw_template(name, template)
                .expect("Tera::add_raw_template");
        }
    }
}
