#pragma once

#include <string>
#include <stack>
#include "XmlDocument.h"

class XmlParser
{
public:
    enum class DocumentState
    {
        Await_Prolog,
        Build_Prolog,
        Await_Element,
        Build_Element,
        Close_Element
    };

    enum class LineState
    {
        Await_Tag_Open,
        Await_Tag_Follower,
        Await_Tag_Name,
        Await_Tag_Name_End,
        Await_Attribute_Name,
        Await_Attribute_Name_End,
        Await_Attribute_Value,
        Await_Attribute_Value_End,
        Await_Text_End
    };

private:

    DocumentState mDocumentState;
    LineState mLineState;
    XmlDocumentPtr mDocument;
    std::stack<XmlElement*> mWorkingElements;
    std::string mWorkingAttributeName;
    std::string mWorkingTagName;
    std::string mWorkingAttributeValue;
    std::string mWorkingText;

public:

    XmlParser();

    void ProcessLine(const std::string& input);

    XmlDocumentPtr GetDocument() const;

private:

    void OnLeftBracket();

    void OnRightBracket();

    void OnQuestionMark();

    void OnForwardSlash();

    void OnChar(char c);

    void OnSpace(char c);

    void OnAlphaNumeric(char c);

    void OnNonAlphaNumeric(char c);

    void OnEquals();

    void OnDoubleQuote();

    void OnTagOpen();

    void OnTagNameStart(char c);

    void OnTagNameEnd();

    void OnTagClose();

    void OnTextStart(char c);

    void OnTextEnd();

    void OnAttributeNameStart(char c);

    void OnAttributeNameEnd();

    void OnAttributeValueStart();

    void OnAttributeValueEnd();

    void OnPrologId();

    void OnStartProlog();

    void onFinishProlog();

    void onElementTagEnd();
};
