use serde::Serialize;

use super::render_context::RenderContext;
use crate::context::macros::push_file;
use crate::error::CustomError;
use crate::intermediate::get_web_path;
use crate::intermediate::BlogPost;
use crate::intermediate::BlogPostPage;

use super::footnote_definition::RenderRealFootnoteDefinition;
use super::macros::render;
use super::GlobalSettings;
use super::PageHeader;
use super::RenderDocumentElement;

#[derive(Debug)]
pub(crate) struct RenderBlogPostPageInput<'a> {
    #[allow(dead_code)]
    post: &'a BlogPost,
    page: &'a BlogPostPage,
}

impl<'a> RenderBlogPostPageInput<'a> {
    pub(crate) fn new(post: &'a BlogPost, page: &'a BlogPostPage) -> RenderBlogPostPageInput<'a> {
        RenderBlogPostPageInput { post, page }
    }
}

#[derive(Debug, Serialize)]
#[serde(tag = "type")]
#[serde(rename = "blog_post_page")]
pub(crate) struct RenderBlogPostPage {
    global_settings: GlobalSettings,

    page_header: Option<PageHeader>,

    /// The title that will be shown visibly on the page.
    title: Option<String>,

    self_link: Option<String>,

    children: Vec<RenderDocumentElement>,

    footnotes: Vec<RenderRealFootnoteDefinition>,
}

render!(
    RenderBlogPostPage,
    RenderBlogPostPageInput,
    original,
    render_context,
    {
        push_file!(render_context, &original.page.src, {
            let css_files = vec![
                get_web_path(
                    render_context.config,
                    render_context.output_root_directory,
                    render_context.output_file,
                    "stylesheet/reset.css",
                )?,
                get_web_path(
                    render_context.config,
                    render_context.output_root_directory,
                    render_context.output_file,
                    "stylesheet/main.css",
                )?,
            ];
            let js_files = vec![get_web_path(
                render_context.config,
                render_context.output_root_directory,
                render_context.output_file,
                "blog_post.js",
            )?];
            let global_settings =
                GlobalSettings::new(original.page.title.clone(), css_files, js_files);
            let page_header = PageHeader::new(
                render_context.config.get_site_title().map(str::to_string),
                Some(get_web_path(
                    render_context.config,
                    render_context.output_root_directory,
                    render_context.output_file,
                    "",
                )?),
            );
            let link_to_blog_post = get_web_path(
                render_context.config,
                render_context.output_root_directory,
                render_context.output_file,
                render_context
                    .output_file
                    .strip_prefix(render_context.output_root_directory)?,
            )?;

            let children = {
                let mut children = Vec::new();

                for child in original.page.children.iter() {
                    children.push(RenderDocumentElement::new(render_context.clone(), child)?);
                }

                children
            };

            let footnotes = {
                let mut ret = Vec::new();

                for footnote in original.page.footnotes.iter() {
                    ret.push(RenderRealFootnoteDefinition::new(
                        render_context.clone(),
                        footnote,
                    )?);
                }

                ret
            };

            let ret = RenderBlogPostPage {
                global_settings,
                page_header: Some(page_header),
                title: original.page.title.clone(),
                self_link: Some(link_to_blog_post),
                children,
                footnotes,
            };
            Ok(ret)
        })
    }
);