use super::{
    pagination::{render_paginated, PaginatableTemplate, PaginationInfo},
    util::output_rendered_template,
    util::templates::{filters, TemplateCommon},
    HtmlContent, Post,
};
use askama::Template;
use chrono::Datelike;
use std::collections::HashMap;

pub fn generate(posts: &[Post<HtmlContent>]) {
    let mut years: HashMap<i32, Vec<&Post<HtmlContent>>> = HashMap::new();
    for post in posts {
        let year_posts = years.entry(post.metadata.date.year()).or_default();
        year_posts.push(post);
    }

    let mut years = years.into_iter().collect::<Vec<_>>();
    years.sort_by_key(|(year, _)| *year);
    years.reverse();

    output_rendered_template(&ArchiveTemplate { years: &years }, "archive/index.html")
        .expect("generating archive");

    for (year, posts) in years {
        let template = YearTemplate {
            year,
            posts: &[],
            pagination_info: Default::default(),
        };
        render_paginated(&template, &posts, year.to_string()).expect("generate year");
    }
}

#[derive(Template)]
#[template(path = "archive.html")]
struct ArchiveTemplate<'a> {
    years: &'a Vec<(i32, Vec<&'a Post<HtmlContent>>)>,
}

impl<'a> TemplateCommon for ArchiveTemplate<'a> {}

impl<'a> ArchiveTemplate<'a> {
    fn permalink(&self) -> &'static str {
        "/archive/"
    }
}

#[derive(Template)]
#[template(path = "year.html")]
struct YearTemplate<'a> {
    year: i32,
    posts: &'a [&'a Post<HtmlContent>],
    pagination_info: PaginationInfo,
}

impl<'a> TemplateCommon for YearTemplate<'a> {}

impl<'a> PaginatableTemplate<'a> for YearTemplate<'a> {
    fn with_posts(
        &'a self,
        posts: &'a [&'a Post<HtmlContent>],
        pagination_info: PaginationInfo,
    ) -> Self {
        Self {
            posts,
            pagination_info,
            ..*self
        }
    }
}

impl<'a> YearTemplate<'a> {
    fn permalink(&self) -> String {
        format!("/{}/", self.year)
    }
}
