#pragma once

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

class MarkdownDocument;
class MarkdownElement;
class MarkdownInlineElement;
class MarkdownBulletList;

class MarkdownParser
{
public:
    MarkdownParser();

    ~MarkdownParser();

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

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

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

    bool isInMultilineBlock() const;

    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;

    void onFoundMultiLineQuote(const std::string& line);
    void onFoundCustomMultiLineBlock(const std::string& line, unsigned 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);

    unsigned mCustomDelimiterIndex{0};
    std::vector<std::string> mCustomMultilineDelimiters;
    std::vector<std::string> mCustomInlineDelimiters;

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

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

    std::unique_ptr<MarkdownDocument> mMarkdownDocument;
};
