use super::posts::parse::Tag;
use super::posts::{HtmlContent, Post};
use super::util::output_writer;
use chrono::{DateTime, Utc};
use rss::{Category, ChannelBuilder, Guid, Item, ItemBuilder};
use std::collections::HashMap;
use std::path::PathBuf;

pub fn generate(posts: &[Post<HtmlContent>], tags: &HashMap<&Tag, Vec<&Post<HtmlContent>>>) {
    let all_feed = ChannelBuilder::default()
        .title("Shadowfacts")
        .link("https://shadowfacts.net")
        .last_build_date(Some(rfc_822(Utc::now())))
        .items(posts.iter().map(to_rss_item).collect::<Vec<_>>())
        .build();
    let all_writer = output_writer("/feed.xml").expect("feed.xml");
    all_feed
        .pretty_write_to(all_writer, b' ', 2)
        .expect("write feed.xml");

    for (tag, posts) in tags {
        let tag_feed = ChannelBuilder::default()
            .title(format!("Shadowfacts ({})", tag.name))
            .link(format!("https://shadowfacts.net/{}", tag.slug))
            .last_build_date(Some(rfc_822(Utc::now())))
            .items(posts.iter().map(|&p| to_rss_item(p)).collect::<Vec<_>>())
            .build();
        let mut buf = PathBuf::from(&tag.slug);
        buf.push("feed.xml");
        let tag_writer = output_writer(buf).expect("tag feed.xml");
        tag_feed
            .pretty_write_to(tag_writer, b' ', 2)
            .expect("write tag feed.xml");
    }
}

fn rfc_822(datetime: DateTime<Utc>) -> String {
    datetime.format("%a, %d %b %Y %H:%M:%S %z").to_string()
}

fn to_rss_item(post: &Post<HtmlContent>) -> Item {
    ItemBuilder::default()
        .title(Some(post.metadata.title.clone()))
        .link(Some(format!("https://shadowfacts.net{}", post.permalink())))
        .guid(Some(Guid {
            value: format!("https://shadowfacts.net{}", post.permalink()),
            permalink: true,
        }))
        .pub_date(Some(rfc_822(post.metadata.date.into())))
        .categories(
            post.metadata
                .tags
                .as_ref()
                .map(|tags| {
                    tags.iter()
                        .map(|t| Category {
                            name: t.name.clone(),
                            domain: None,
                        })
                        .collect::<Vec<_>>()
                })
                .unwrap_or(vec![]),
        )
        .content(Some(post.content.html().to_owned()))
        .build()
}
