#include "MarkdownComponents.h"

#include "MarkdownCustomElement.h"
#include "StringUtils.h"

MarkdownTextSpan::Type MarkdownTextSpan::getType() const
{
    return Type::TEXT_SPAN;
}

MarkdownParagraph::Type MarkdownParagraph::getType() const
{
    return Type::PARAGRAPH;
}

void MarkdownElementWithChildren::addChild(std::unique_ptr<MarkdownInlineElement> child)
{
    mChildren.push_back(std::move(child));
}

std::size_t MarkdownElementWithChildren::getNumChildren() const
{
    return mChildren.size();
}

MarkdownInlineElement* MarkdownElementWithChildren::getChild(std::size_t idx) const
{
    return mChildren[idx].get();
}

MarkdownInlineElement* MarkdownElementWithChildren::getLastChild() const
{
    if (mChildren.empty())
    {
        return nullptr;
    }
    else
    {
        return mChildren[mChildren.size()-1].get();
    }
}

std::vector<MarkdownLink*> MarkdownElementWithChildren::getAllLinks() const
{
    std::vector<MarkdownLink*> links;
    for(auto& child : mChildren)
    {
        if (child->getType() == Type::LINK)
        {
            links.push_back(dynamic_cast<MarkdownLink*>(child.get()));
        }
    }
    return links;
}

MarkdownBulletItem::Type MarkdownBulletItem::getType() const
{
    return Type::BULLET_ITEM;
}

MarkdownBulletList::Type MarkdownBulletList::getType() const
{
    return Type::BULLET_LIST;
}

void MarkdownBulletList::addChild(std::unique_ptr<MarkdownBulletItem> child)
{
    mChildren.push_back(std::move(child));
}

std::size_t MarkdownBulletList::getNumChildren() const
{
    return mChildren.size();
}

MarkdownBulletItem* MarkdownBulletList::getChild(std::size_t idx) const
{
    return mChildren[idx].get();
}

MarkdownHeading::MarkdownHeading(unsigned level)
    : mLevel(level)
{

}

MarkdownHeading::Type MarkdownHeading::getType() const
{
    return Type::HEADING;
}

unsigned MarkdownHeading::getLevel() const
{
    return mLevel;
}

MarkdownInlineQuote::Type MarkdownInlineQuote::getType() const
{
    return Type::INLINE_QUOTE;
}

MarkdownCustomInline::MarkdownCustomInline(MarkdownCustomElementContext* customElement)
    : mCustomElement(customElement)
{
}

MarkdownCustomInline::Type MarkdownCustomInline::getType() const
{
    return Type::CUSTOM_INLINE;
};

std::string MarkdownCustomInline::getTextContent() const
{
    return mCustomElement->getOutputLeftDelimiter() + MarkdownElement::getTextContent() + mCustomElement->getOutputRightDelimiter();
}

MarkdownLink::MarkdownLink(const std::string& target)
    : mTarget(target)
{

}

const std::string& MarkdownLink::getTarget() const
{
    return mTarget;
}

MarkdownLink::Type MarkdownLink::getType() const
{
    return Type::LINK;
}

MarkdownImage::MarkdownImage(const std::string& source, const std::string& alt)
    : mSource(source),
      mAlt(alt)
{

}

MarkdownImage::Type MarkdownImage::getType() const
{
    return Type::IMAGE;
}

const std::string& MarkdownImage::getSource() const
{
    return mSource;
}

const std::string& MarkdownImage::getAlt() const
{
    return mAlt;
}

MarkdownMultilineQuote::MarkdownMultilineQuote(const std::string& tag)
    : mTag(tag)
{

}

MarkdownMultilineQuote::Type MarkdownMultilineQuote::getType() const
{
    return Type::MULTILINE_QUOTE;
}


MarkdownCustomMultiLine::MarkdownCustomMultiLine(const std::string& tag, MarkdownCustomElementContext* customElement)
    : mTag(tag),
      mCustomElement(customElement)
{

}

MarkdownCustomMultiLine::Type MarkdownCustomMultiLine::getType() const
{
    return Type::CUSTOM_MULTILINE;
}

std::string MarkdownCustomMultiLine::getTextContent() const
{
    return mCustomElement->getOutputLeftDelimiter() + "\n" + MarkdownElement::getTextContent() + mCustomElement->getOutputRightDelimiter();
}
