mod archive;
mod copy;
mod css;
mod highlight;
mod home;
mod markdown;
mod pagination;
mod posts;
mod rss;
mod tags;
mod tutorials;
mod tv;
mod util;

pub use crate::generator::posts::parse::{HtmlContent, Post};
use std::path::{Component, Path, PathBuf};

pub async fn generate() -> anyhow::Result<Vec<Post<HtmlContent>>> {
    std::fs::create_dir_all("out").expect("creating output dir");

    let posts = posts::parse().await?;
    let post_refs = posts.iter().collect::<Vec<_>>();
    let tags = tags::generate(&posts);
    posts::generate(&posts)?;
    home::generate(&post_refs)?;
    rss::generate(&posts, &tags);
    archive::generate(&posts);

    css::generate()?;

    copy::copy();

    tv::generate();
    tutorials::generate();

    Ok(posts)
}

pub fn content_path(p: impl AsRef<Path>) -> PathBuf {
    let mut buf = PathBuf::from("site/");
    join_abs(&mut buf, p.as_ref());
    buf
}

pub fn output_path(p: impl AsRef<Path>) -> PathBuf {
    let mut buf = PathBuf::from("out/");
    join_abs(&mut buf, p.as_ref());
    buf
}

fn join_abs(buf: &mut PathBuf, p: &Path) {
    for comp in p.components() {
        match comp {
            Component::RootDir => (),
            Component::CurDir => (),
            Component::Normal(c) => buf.push(c),
            Component::Prefix(_) => panic!("prefixes are unsupported"),
            Component::ParentDir => {
                buf.pop();
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::join_abs;
    use std::path::{Path, PathBuf};

    #[test]
    fn test_join_abs() {
        let mut buf = PathBuf::from("site/");
        join_abs(&mut buf, Path::new("/2022/test/"));
        assert_eq!(buf, PathBuf::from("site/2022/test/"));
    }
}
