extern crate regex;
extern crate rss;

use regex::Regex;
use rss::{ChannelBuilder, Item};
use std::error;
use std::fs;
use std::fs::File;
use std::io::prelude::*;

fn main() -> Result<(), Box<dyn error::Error>> {
    // create rss channel for mycelial.technology
    let mut channel = ChannelBuilder::default()
        .title("mycelial technology")
        .link("https://mycelial.technology")
        .description(
            "glyph's RSS feed. Biophilic musings on carbon-based and silicon-based technologies.",
        )
        .build()
        .unwrap();

    // list template directories containing articles for syndication
    let bacteria = "./templates/bacteria";
    let computers = "./templates/computers";
    let fungi = "./templates/fungi";
    let plants = "./templates/plants";

    // add directories to a vector
    let mut dirs = Vec::new();
    dirs.push(bacteria);
    dirs.push(computers);
    dirs.push(fungi);
    dirs.push(plants);

    // create vectors for item fields
    let mut titles = Vec::new();
    let mut pub_dates = Vec::new();
    let mut urls = Vec::new();
    let mut articles = Vec::new();

    // loop through template directories and extract item field values
    for dir in dirs {
        for entry in fs::read_dir(dir)? {
            let entry = entry?;
            let path = entry.path();

            // populate item url vector from article filenames
            let re_url = Regex::new("./templates/(.*).html.tera")?;
            let caps_url = re_url.captures(&path.to_str().unwrap());
            if let Some(url) = caps_url {
                let article_url = url[1].replace("_", "-");
                let full_url = format!("https://mycelial.technology/{}", article_url);
                urls.push(full_url);
            };

            // open the file (article) and read it to a string
            let mut file = File::open(path)?;
            let mut contents = String::new();
            file.read_to_string(&mut contents)?;

            // populate item title vector from article heading
            let re_h2 = Regex::new("<h2>(.*)</h2>")?;
            let caps_h2 = re_h2.captures(&contents);
            if let Some(title) = caps_h2 {
                titles.push(title[1].to_string());
            };

            // populate pub_date vector from first italic element in article
            let re_i = Regex::new("<i>(.*)</i>")?;
            let caps_i = re_i.captures(&contents);
            if let Some(date) = caps_i {
                pub_dates.push(date[1].to_string());
            };

            // populate article content vector from article element
            let re_article = Regex::new(r"<article>[\s\S]*</article>")?;
            let caps_article = re_article.captures(&contents);
            if let Some(content) = caps_article {
                articles.push(content[0].to_string());
            };
        }
    }

    // get length of titles vector (serves as proxy for total number of articles)
    let library = titles.len();

    // create vector for channel items
    let mut items = Vec::new();

    // loop through vectors of item fields and create items accordingly
    for x in 0..library {
        let mut item = Item::default();
        item.set_title(titles[x].to_string());
        item.set_link(urls[x].to_string());
        item.set_pub_date(pub_dates[x].to_string());
        item.set_description(articles[x].to_string());
        items.push(item)
    }

    // add the items to the channel
    channel.set_items(items);

    // write the channel to file
    let rss_file = File::create("static/feed.rss")?;
    channel.write_to(rss_file)?;

    Ok(())
}
