//! # Rust Letter Frontend
//!
//! Rendering functions for the site using [Dioxus](https://dioxuslabs.com/).

#![allow(non_snake_case)]

/// A module that handles the functions needed
/// to render the site.
pub mod void_app {
    // import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
    pub use dioxus::prelude::*;
    use rust_embed::RustEmbed;
    use markdown::{self, Options};

    #[cfg(any(target_family = "wasm"))]
    use dioxus_router::{Router, Route, Link};

    #[derive(PartialEq, Props)]
    pub struct PoemRequest {
        slug: String,
    }

    #[derive(PartialEq, Props)]
    struct PoemData {
        title: Option<String>,
        content: Option<String>,
        creation_date: Option<String>,
        slug: Option<String>,
    }
    #[derive(RustEmbed)]
    #[folder = "data/poems"]
    pub struct Poems;

    #[cfg(target_family = "wasm")]
    pub fn DioxusApp(cx: Scope) -> Element {
        cx.render(rsx! {
            Router {
                Route { to: "/", HomePage {} }
                Route { to: "/poem/:slug/", PoemPage {} }
            }
        })
    }

    /// Renders the app and returns the rendered Element.
    pub fn HomePage(cx: Scope) -> Element {
        cx.render(rsx!{
            div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
                div { class: "container space-y-4 mx-auto p-4",
                    div { class: "p-4 space-y-2 ring-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light",
                        p { class: "text-lg text-center",
                            "A Letter to the Void"
                        }
                    }
                    Poems::iter().map(|p| {
                        let filename = p.to_string();
                        let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
                        let mut poem_to_str = std::str::from_utf8(poem_content.data.as_ref()).expect("Title is valid UT8.").lines();
                        let title_markdown = poem_to_str.next().expect("No title specified.");
                        let title = markdown::to_html_with_options(title_markdown, &Options::gfm()).unwrap();
                        let slug = String::from(filename.trim_end_matches(".md"));
                        cx.render(rsx!(
                            ul { class: "space-y-4",
                                PoemButton { title: title, slug: slug }
                            }
                        ))
                    })
                }
            }
        })
    }

    #[cfg(any(target_family = "unix", target_family = "windows"))]
    pub fn PoemPage(cx: Scope<PoemRequest>) -> Element {
        let slug = cx.props.slug.clone();
        cx.render(rsx!{
            div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
                div { class: "container space-y-4 mx-auto p-4", GetPoem { slug: slug } }
            }
        })
    }

    #[cfg(target_family = "wasm")]
    fn PoemPage(cx: Scope) -> Element {
        log::trace!("Test");
        let slug = String::from(dioxus_router::use_route(cx).segment("slug").expect("No slug specified."));

        log::trace!("{slug}");

        cx.render(rsx!{
            div { class: "min-h-screen font-nerd bg-alice-werefox-grey-light dark:bg-alice-werefox-grey",
                div { class: "container space-y-4 mx-auto p-4", GetPoem { slug: slug } }
            }
        })
    }

    #[cfg(any(target_family = "unix", target_family = "windows"))]
    fn PoemButton(cx: Scope<PoemData>) -> Element {
        let title = cx.props.title.clone().expect("No title specified.");
        let slug = cx.props.slug.clone().expect("No slug specified.");
        let slug_ref = slug.as_str();
        cx.render(rsx!{
            div {
                a { href: "/poem/{slug_ref}",
                    li { class: "p-4 ml-6 mr-6 space-y-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition",
                        div { class: "text-lg text-center", "{title}" }
                    }
                }
            }
        })
    }

    #[cfg(target_family = "wasm")]
    fn PoemButton(cx: Scope<PoemData>) -> Element {
        let title = cx.props.title.clone().expect("No title specified.");
        let slug = cx.props.slug.clone().expect("No slug specified.");
        let slug_ref = slug.as_str();
        cx.render(rsx!{
            div {
                Link { to: "/poem/{slug_ref}",
                    li { class: "p-4 ml-6 mr-6 space-y-2 ring-2 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark ring-alice-werefox-red-dark dark:ring-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light hover:text-alice-werefox-blue-dark dark:hover:text-alice-werefox-blue-light hover:ring-alice-werefox-blue dark:hover:ring-alice-werefox-blue hover:animate-yip transition",
                        div { class: "text-lg text-center", dangerous_inner_html: "{title}" }
                    }
                }
            }
        })
    }

    fn GetPoem(cx: Scope<PoemData>) -> Element {
        let filename = String::from(String::from(cx.props.slug.clone().expect("No slug specified.")) + ".md");
        let creation_date = String::from(String::from("<br>Written on: ") + filename.split("_").next().unwrap());
        let poem_content = Poems::get(&filename).expect("Found poem {filename:?}");
        let mut poem_to_str = std::str::from_utf8(poem_content.data.as_ref()).expect("Title is valid UT8.").lines();
        let poem_title = poem_to_str.next().unwrap();
        let poem_content = poem_to_str.into_iter().collect::<Vec<&str>>().join("\n");
        let poem_title_to_html_string = markdown::to_html_with_options(poem_title, &Options::gfm()).unwrap();
        let poem_content_to_html_string = markdown::to_html_with_options(poem_content.as_str(), &Options::gfm()).unwrap();
        cx.render(rsx!{
            MakePoem{ title: poem_title_to_html_string, content: poem_content_to_html_string, creation_date: creation_date } }
        )
    }

    #[cfg(any(target_family = "unix", target_family = "windows"))]
    fn RenderPoemTitle(cx: Scope<PoemData>) -> Element {
        let title = cx.props.title.clone().expect("No title specified.");
        cx.render(rsx!{
            span { class: "mx-auto max-w-fit flex justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
                "{title}"
            }
        })
    }

    #[cfg(target_family = "wasm")]
    fn RenderPoemTitle(cx: Scope<PoemData>) -> Element {
        let title = cx.props.title.clone().expect("This poem has an empty title.");
        cx.render(rsx!{
            p { class: "mx-auto max-w-fit flex justify-center bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
                dangerous_inner_html: "{title}",
            }
        })
    }

    #[cfg(any(target_family = "unix", target_family = "windows"))]
    fn RenderPoemElement(cx: Scope<PoemData>) -> Element {
        let content = cx.props.content.clone().expect("No content specified.");
        let creation_date = cx.props.creation_date.clone().expect("No creation date specified.");
        cx.render(rsx!{
            div { class: "font-nerd flex flex-col space-y-4 mx-4 py-4", "{content}{creation_date}" }
        })
    }

    #[cfg(target_family = "wasm")]
    fn RenderPoemElement(cx: Scope<PoemData>) -> Element {
        let content = cx.props.content.clone().expect("No content specified.");
        let creation_date = cx.props.creation_date.clone().expect("No creation date specified.");
        cx.render(rsx!{
            div {
                class: "font-nerd flex flex-col space-y-4 mx-4 py-4",
                dangerous_inner_html: "{content}{creation_date}"
            }
        })
    }

    fn MakePoem(cx: Scope<PoemData>) -> Element {
        let title = cx.props.title.clone().expect("No title specified.");
        let creation_date = cx.props.creation_date.clone().expect("No creation date specified.");
        let content = cx.props.content.clone().expect("No content specified.");
        cx.render(rsx!{
            div { class: "flex-col space-y-4",
                RenderPoemTitle { title: title.clone() }
                details { class: "mx-auto max-w-fit space-y-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-4 border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
                    summary { class: "flex justify-center border-4 bg-alice-werefox-grey-lightest dark:bg-alice-werefox-grey-dark border-alice-werefox-red-dark dark:border-alice-werefox-red text-alice-werefox-red-dark dark:text-alice-werefox-red-light p-4",
                        "Open"
                    }
                    RenderPoemElement { content: content.clone(), creation_date: creation_date.clone() }
                }
            }
        })
    }
}
