#include "MarkdownConverter.h"

#include "HtmlDocument.h"
#include "HtmlElement.h"
#include "HtmlParagraphElement.h"
#include "HtmlBodyElement.h"
#include "HtmlTextRun.h"
#include "MarkdownElement.h"
#include "MarkdownComponents.h"

#include "MarkdownDocument.h"

void MarkdownConverter::onBlockElement(MarkdownElementWithChildren* mdElement, HtmlElement* htmlElement) const
{
    for(unsigned idx=0; idx< mdElement->getNumChildren(); idx++)
    {
        auto child = mdElement->getChild(idx);
        if (child->getType() == MarkdownElement::Type::INLINE_QUOTE)
        {
            auto html_quote = std::make_unique<HtmlCodeElement>();
            html_quote->setText(child->getTextContent());
            htmlElement->addChild(std::move(html_quote));
        }
        else if (child->getType() == MarkdownElement::Type::CUSTOM_INLINE)
        {
            auto html_text = std::make_unique<HtmlTextRun>();
            html_text->setText(child->getTextContent());
            htmlElement->addChild(std::move(html_text));
        }
        else if(child->getType() == MarkdownElement::Type::TEXT_SPAN)
        {
            auto html_text = std::make_unique<HtmlTextRun>();
            html_text->setText(child->getTextContent());
            htmlElement->addChild(std::move(html_text));
        }
        else if(child->getType() == MarkdownElement::Type::LINK)
        {
            auto link_element = dynamic_cast<MarkdownLink*>(child);
            auto html_text = std::make_unique<HtmlHyperlinkElement>(link_element->getTarget());
            html_text->setText(link_element->getTextContent());
            htmlElement->addChild(std::move(html_text));
        }
        else if(child->getType() == MarkdownElement::Type::IMAGE)
        {
            auto link_element = dynamic_cast<MarkdownImage*>(child);
            auto html_text = std::make_unique<HtmlImageElement>(link_element->getSource(), link_element->getAlt());
            htmlElement->addChild(std::move(html_text));
        }
    }
}

void MarkdownConverter::convert(MarkdownDocument* markdownDoc, HtmlElement* parentElement) const
{
    for(unsigned idx=0; idx<markdownDoc->getNumElements();idx++)
    {
        auto md_element = markdownDoc->getElement(idx);

        if (md_element->getType() == MarkdownElement::Type::HEADING)
        {
            auto heading_level = dynamic_cast<MarkdownHeading*>(md_element)->getLevel();
            auto html_element = std::make_unique<HtmlHeadingElement>(heading_level);
            html_element->setText(md_element->getTextContent());

            parentElement->addChild(std::move(html_element));
        }
        else if(md_element->getType() == MarkdownElement::Type::PARAGRAPH)
        {
            auto html_p_element = std::make_unique<HtmlParagraphElement>();
            auto para_element = dynamic_cast<MarkdownParagraph*>(md_element);

            onBlockElement(para_element, html_p_element.get());

            parentElement->addChild(std::move(html_p_element));
        }
        else if(md_element->getType() == MarkdownElement::Type::BULLET_LIST)
        {
            auto list_element = dynamic_cast<MarkdownBulletList*>(md_element);
            auto html_list = std::make_unique<HtmlUnorderedList>();
            for(unsigned idx=0; idx< list_element->getNumChildren(); idx++)
            {
                auto child = list_element->getChild(idx);
                auto html_list_item = std::make_unique<HtmlListItem>();

                onBlockElement(child, html_list_item.get());

                html_list->addChild(std::move(html_list_item));
            }
            parentElement->addChild(std::move(html_list));
        }
        else if(md_element->getType() == MarkdownElement::Type::MULTILINE_QUOTE)
        {
            auto html_quote = std::make_unique<HtmlCodeElement>();
            html_quote->setText(md_element->getTextContent());
            parentElement->addChild(std::move(html_quote));
        }
        else if(md_element->getType() == MarkdownElement::Type::CUSTOM_MULTILINE)
        {
            auto html_text = std::make_unique<HtmlTextRun>();
            html_text->setText("\n" + md_element->getTextContent() + "\n");
            parentElement->addChild(std::move(html_text));
        }
    }
}

std::unique_ptr<HtmlDocument> MarkdownConverter::convert(MarkdownDocument* markdownDoc) const
{
    auto html_doc = std::make_unique<HtmlDocument>();

    auto body_element = html_doc->getBodyElement();
    convert(markdownDoc, body_element);

    return html_doc;
}

