use anyhow::{Context, Result};
use serde::Serialize;
use std::collections::HashMap;
use tinytemplate::TinyTemplate;

pub struct Template<'a>(TinyTemplate<'a>);

impl Template<'_> {
    const LINK_TEMPLATE: &'_ str = r#"
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <link rel="canonical" href="{url}" />
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <meta http-equiv="refresh" content="0;url={url}" />
    </head>
    <body>
        <h1>Redirecting...</h1>
          <a href="{url}">Click here if you are not redirected.</a>
          <script>location.href="{url}"</script>
    </body>
</html>
"#;

    const LINK_INDEX: &'_ str = r#"
<!doctype html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">

      <title>A static url shortener</title>
      <meta name="description" content="This site was generated by https://github.com/adriantombu/mubo">
    </head>

    <body>
        <ul>
            {{for link in links}}
                <li><a href="./r/{link.key}/">/r/{link.key}/</a></li>
            {{endfor}}
        </ul>
    </body>
</html>
"#;

    pub fn new() -> Result<Self> {
        let mut tt = TinyTemplate::new();
        tt.add_template("link", Self::LINK_TEMPLATE)
            .context("Failed to load the template LINK_TEMPLATE")?;
        tt.add_template("index", Self::LINK_INDEX)
            .context("Failed to load the template LINK_INDEX")?;

        Ok(Template(tt))
    }

    pub fn render<T, U>(&self, template: &str, context: &HashMap<T, U>) -> Result<String>
    where
        T: Serialize,
        U: Serialize,
    {
        Ok(self.0.render(template, &context)?)
    }
}
