#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use]
extern crate log;
#[macro_use]
extern crate rocket;
extern crate rocket_contrib;
#[macro_use]
extern crate serde_derive;
extern crate tera;

use std::path::{Path, PathBuf};

use rocket::response::NamedFile;
use rocket_contrib::templates::Template;

#[derive(Debug, Serialize)]
struct FlashContext {
    flash_name: Option<String>,
    flash_msg: Option<String>,
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("static/").join(file)).ok()
}

#[get("/art")]
fn art() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("art", &context)
}

#[get("/background")]
fn background() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("background", &context)
}

#[get("/bacteria")]
fn bacteria() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("bacteria", &context)
}

#[get("/bacteria/sauerkraut-beginnings")]
fn bacteria_sauerkraut_beginnings() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("bacteria/sauerkraut_beginnings", &context)
}

#[get("/bacteria/sauerkraut-bottled")]
fn bacteria_sauerkraut_bottled() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("bacteria/sauerkraut_bottled", &context)
}

#[get("/computers")]
fn computers() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("computers", &context)
}

#[get("/computers/esp8266-dht11")]
fn computers_esp8266_dht11() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("computers/esp8266_dht11", &context)
}

#[get("/computers/i2c-adventures")]
fn computers_i2c_adventures() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("computers/i2c_adventures", &context)
}

#[get("/computers/rust-compilation")]
fn computers_rust_compilation() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("computers/rust_compilation", &context)
}

#[get("/fungi")]
fn fungi() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("fungi", &context)
}

#[get("/fungi/grow-together")]
fn fungi_grow_together() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("fungi/grow_together", &context)
}

#[get("/fungi/lichen-space")]
fn fungi_lichen_space() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("fungi/lichen_space", &context)
}

#[get("/")]
fn home() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("home", &context)
}

#[get("/lists")]
fn lists() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("lists", &context)
}

#[get("/plants")]
fn plants() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("plants", &context)
}

#[get("/plants/aloe-there")]
fn plants_aloe_there() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("plants/aloe_there", &context)
}

#[get("/plants/blueberry-dance")]
fn plants_blueberry_dance() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("plants/blueberry_dance", &context)
}

#[get("/plants/botanical-deceptions")]
fn plants_botanical_deceptions() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("plants/botanical_deceptions", &context)
}

#[get("/plants/potato-tech")]
fn plants_potato_tech() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("plants/potato_tech", &context)
}

#[get("/meditation")]
fn meditation() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("meditation", &context)
}

#[get("/support")]
fn support() -> Template {
    let context = FlashContext {
        flash_name: None,
        flash_msg: None,
    };
    Template::render("support", &context)
}

#[catch(404)]
fn not_found() -> Template {
    debug!("404 Page Not Found");
    let context = FlashContext {
        flash_name: Some("error".to_string()),
        flash_msg: Some("No resource found for given URL".to_string()),
    };
    Template::render("not_found", context)
}

fn main() {
    rocket::ignite()
        .mount(
            "/",
            routes![
                files,
                art,
                background,
                bacteria,
                bacteria_sauerkraut_beginnings,
                bacteria_sauerkraut_bottled,
                computers,
                computers_esp8266_dht11,
                computers_i2c_adventures,
                computers_rust_compilation,
                fungi,
                fungi_grow_together,
                fungi_lichen_space,
                home,
                lists,
                plants,
                plants_aloe_there,
                plants_blueberry_dance,
                plants_botanical_deceptions,
                plants_potato_tech,
                meditation,
                support
            ],
        )
        .register(catchers![not_found])
        .attach(Template::fairing())
        .launch();
}
