use std::fs::{ File, create_dir_all };
use std::path::Path;

use handlebars::Handlebars;
use serde::Serialize;

use super::loader;
use super::models::post::Post;
use super::models::section::Section;

#[derive(Serialize)]
struct TemplateData<'a> {
  section: &'a Section,
  post: Option<&'a Post>,
}

pub fn landing_page() {
  let mut handlebars = Handlebars::new();

  match handlebars.register_template_file("landing", "./templates/landing.hbs") {
    Err(error) => panic!("Could not load landing template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("header", "./templates/header.hbs") {
    Err(error) => panic!("Could not load header template: {}", error),
    Ok(_) => (),
  };

  let data = "";
  let mut output_file = match File::create("./generated/index.html") {
    Err(error) => panic!("Could not create landing index: {}", error),
    Ok(file) => file,
  };

  match handlebars.render_to_write("landing", &data, &mut output_file) {
    Err(error) => panic!("Error rendering landing: {}", error),
    Ok(_) => (),
  };
}

pub fn sections() {
  let sections = loader::sections();
  let mut handlebars = Handlebars::new();

  load_templates(&mut handlebars);
  
  for section in &sections {
    let section_path = Path::new("./generated").join(section.url.to_owned());
    match create_dir_all(section_path) {
      Ok(_) => println!("[GEN] {} -> Created folder at url {}", section.title, section.url),
      Err(error) => panic!("Error creating section folder: {}", error),
    };

    // Generate posts
    for post in &section.posts {
      let data = TemplateData {
        post: Some(post),
        section: section,
      };

      let post_path = Path::new("./generated").join(section.url.to_owned()).join(post.url.to_owned());
      let mut output_file = match File::create(post_path) {
        Err(error) => panic!("Could not create post: {}", error),
        Ok(file) => file,
      };

      match handlebars.render_to_write("base", &data, &mut output_file) {
        Err(error) => panic!("Error rendering post: {}", error),
        Ok(_) => println!("[GEN] {} -> Rendered post {}", section.title, post.title),
      };
    }

    // Generate section index

    let data = TemplateData {
      post: None,
      section: section,
    };
    let index_path = Path::new("./generated").join(section.url.to_owned()).join("index.html");
    let mut output_file = match File::create(index_path) {
      Err(error) => panic!("Could not create section index: {}", error),
      Ok(file) => file,
    };

    match handlebars.render_to_write("base_section", &data, &mut output_file) {
      Err(error) => panic!("Error rendering post: {}", error),
      Ok(_) => println!("[GEN] {} -> Rendered index", section.title),
    };
  }
}

fn load_templates(handlebars: &mut Handlebars) {
  match handlebars.register_template_file("base", "./templates/base.hbs") {
    Err(error) => panic!("Could not load base template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("base_section", "./templates/base_section.hbs") {
    Err(error) => panic!("Could not load base template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("header", "./templates/header.hbs") {
    Err(error) => panic!("Could not load header template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("menu", "./templates/menu.hbs") {
    Err(error) => panic!("Could not load menu template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("submenu", "./templates/submenu.hbs") {
    Err(error) => panic!("Could not load submenu template: {}", error),
    Ok(_) => (),
  };

  match handlebars.register_template_file("article", "./templates/article.hbs") {
    Err(error) => panic!("Could not load article template: {}", error),
    Ok(_) => (),
  };
}
