#pragma once
#include <QString>
#include <QList>
#include <QHash>
#include "LexFoundation.h"
#include "SyntaxBase.h"

namespace Syntax 
{
    /**
     *专用于定义语法树的命名空间
     */
    namespace Defines
    {
        /**
         * @brief 元素定义类型
         */
        enum class DefType
        {
            ELEMENT,
            EXPRESSION
        };

        /**
         * 元素定义声明.
         */
        class Elm
        {
        public:
            explicit Elm(const QString &alias_name, bool tail_mark = false);
            virtual ~Elm() = default;

            /**
             * 定义名称，定义别名.
             *
             * \return
             */
            QString aliasName() const;
            /**
             * 引用.
             *
             * \return
             */
            QString refer() const;
            /**
             * 匹配类型.
             *
             * \return 元素或表达式
             */
            virtual DefType type() const;

            /**
             * 是否具有结尾标记.
             *
             * \return
             */
            bool isTail() const;

        private:
            QString name_store;
            bool tail_mark;

        protected:
            DefType type_define;
        };

        /**
         * 表达式定义声明.
         */
        class Exp : public Elm
        {
        public:
            explicit Exp(const QString &alias_name, bool tail_mark = false);
            virtual ~Exp() = default;

            virtual DefType type() const override;
        };
    }


    /**
     * 校验元素，单个token校验.
     */
    class Element
    {
    public:
        typedef bool rst_mark;
        typedef int match_len;

        explicit Element(const QString &token);
        virtual ~Element() = default;

        QString name() const;
        virtual Defines::DefType type() const;

        /**
         * 校验标记序列是否符合语法定义.
         *
         * \param tokens 标记序列
         * \param offset 偏移量
         * \return tuple(完全匹配指示，最大匹配长度)
         */
        virtual std::tuple<rst_mark, match_len>
        elementCheck(const QList<Lex::LexResult> &tokens, int offset) const;

    private:
        QString value_store;
    };

    /**
     * @brief 语法匹配调用链
     */
    class Link
    {
    public:
        Link(const QString &alias, Element *elm);
        virtual ~Link() = default;

        static QString name(const QString &s);
        QString aliasName() const;
        QString refer() const;
        Element* host() const;

        bool tailTest() const;
        void markTail(bool v);

        void appendNext(Link* ins);
        QList<Link*> nextElements() const;

        virtual std::tuple<Element::rst_mark, Element::match_len>
        linkCheck(const QList<Lex::LexResult> &tokens, int offset) const;

    private:
        QString alias_name;
        Element *const host_ins;
        bool tail_mark;

        QList<Link*> next_inss;
    };

    /**
     * @brief 校验表达式，多个语法元素顺序校验
     */
    class Expression : public Element
    {
    public:
        explicit Expression(const QString &name);
        virtual ~Expression() = default;

        Link* parseFlow() const;
        void resetLinks(Link* entry);

        virtual Defines::DefType type() const override;

        /**
         * 校验标记序列是否符合语法定义.
         *
         * \param tokens 标记序列
         * \param offset 偏移量
         * \return tuple(完全匹配指示，最大匹配长度)
         */
        virtual std::tuple<rst_mark, match_len>
        elementCheck(const QList<Lex::LexResult> &tokens, int offset) const override;

    private:
        QString name_store;
        Link* chain_store;
    };



    class XSyntaxBase;

    /**
     * @brief 定义解析规则，支持多范式表达式匹配
     */
    class ParseRule
    {
    public:
        ParseRule(XSyntaxBase *host, const QString &rule_name, unsigned short level,
                  std::function<ParseResult(const QList<Lex::LexResult>&, int)>);
        virtual ~ParseRule() = default;

        int level() const;
        QString name() const;
        void setEnable(bool v);

        void addExpression(const QString &name, const QList<Defines::Elm> &_defines);
        std::tuple<bool, int> tokensMatch(const QList<Lex::LexResult> &token) const;
        ParseResult syntaxTrigger(const QList<Lex::LexResult>& srcs, int count);

    private:
        bool enable_state;
        XSyntaxBase *const host_ins;
        int level_store;
        QString name_store;
        QList<Expression*> expression_list;

        std::function<ParseResult(const QList<Lex::LexResult>&, int)> exc_store;
    };


	/**
	 * @brief 解析器的语法匹配形式
	 */
	enum class MatchType
	{
		Outline,
		Entirely
	};

    /**
     * 基础解析器模型.
     */
    class XSyntaxBase : public Syntax::SyntaxParser
    {
    public:
        explicit XSyntaxBase(const QString &section, MatchType type = MatchType::Entirely);

        Expression* get_expression(const QString &name);
        Element *get_element(const QString &name);

        // 通过 Parse::SyntaxParser 继承
        virtual void docActive(Parse::Result::DocCore *ins) override;
        virtual Parse::Result::DocCore *docRef() const override;
        virtual bool applied(const QList<Lex::LexResult>& seqs) override;
        virtual void reset() override;
        virtual ParseResult parse(QList<Lex::LexResult>& seqs) override;
        virtual QList<Syntax::SyntaxParser*> children() const override;

        virtual Parse::Result::DesNode * currNode() const override;

    protected:
        ParseRule* addRule(const QString &name, unsigned short level, std::function<ParseResult(const QList<Lex::LexResult>&, int)> exc);
        virtual void addChild(QList<Syntax::SyntaxParser*> parsers) override;
        void refocusNode(Parse::Result::DesNode *ins);

        Expression* set_common_expression(const QString &name, const QList<Defines::Elm> &defines);
        void resetMatch(MatchType mtype);

    private:
        MatchType target_type;
        QString section_name;
        int current_level;
        Parse::Result::DesNode *current_node;
        Parse::Result::DocCore *src_ref;

        QHash<QString, Element*> elements_store;
        QHash<QString, Expression*> expressions_store;
        QList<Syntax::SyntaxParser*> child_parsers;

        QHash<QString, ParseRule*> rule_collect;
    };


}
