#pragma once

#include <memory>
#include <string>
#include <vector>

class MarkdownDocument;
class MarkdownElement;
class MarkdownInlineElement;
class MarkdownBulletList;
class MarkdownCustomInlineElementContext;
class MarkdownCustomMultilineElementContext;

class MarkdownParser
{
public:
    MarkdownParser();

    ~MarkdownParser();

    std::unique_ptr<MarkdownDocument> run(const std::string& content);

    void run(const std::string& content, MarkdownDocument* document);

private:
    void addChildToWorkingElement(std::unique_ptr<MarkdownInlineElement> child);

    std::size_t checkForImage(const std::string& lineSection);
    std::size_t checkForLink(const std::string& lineSection);
    std::size_t checkForInlineQuote(const std::string& lineSection);
    std::size_t checkForCustomInline(const std::string& lineSection);

    bool isInMultilineBlock() const;

    void onFoundMultiLineQuote(const std::string& line);
    void onFoundCustomMultiLineBlock(const std::string& line, std::size_t blockSlot);
    void onFoundHeading(const std::string& line);
    void onFoundBulletItem(const std::string& line);

    void onEmptyLine();
    void onSectionFinished();
    void onTextSpanFinished();

    void processLine(const std::string& line);

    bool startsWithMultiLineQuote(const std::string& line) const;
    int startsWithCustomMultilineBlock(const std::string& line) const;
    bool startsWithHeading(const std::string& line) const;
    bool startsWithBulletItem(const std::string& line) const;

    std::size_t mCustomDelimiterIndex{0};

    MarkdownElement* mWorkingElement{nullptr};
    MarkdownBulletList* mWorkingBulletList{nullptr};

    MarkdownInlineElement* mWorkingTextSpan{nullptr};
    std::string mWorkingLine;

    MarkdownDocument* mWorkingDocument{nullptr};
};
