#pragma once

#include <QString>
#include <functional>
#include <QList>
#include "LexFoundation.h"
#include "comndef.h"

namespace Parse 
{
    namespace Result {
        class ProjectCore;
        class DesNode;
        class NamedNode;
        class DocCore;
    }


    namespace Result
    {
        /**
         * 词语块，可以通过文档未知直接获取.
         */
        class Words
        {
        public:
            explicit Words(Result::DesNode* host, Result::DocCore *doc, const QString &value, int row, int col);
            virtual ~Words() = default;

            /**
             * 起始行位置.
             *
             * \return
             */
            virtual int row() const;

            /**
             * 起始列位置.
             *
             * \return
             */
            virtual int column() const;

            /**
             * 次愉快长度.
             *
             * \return 字符数量
             */
            virtual int length() const;

            /**
             * 获取依托节点，悬空节点返回nullptr.
             *
             * \return
             */
            virtual Result::DesNode* host() const;

            /**
             * 隶属文档实例.
             *
             * \return 实例
             */
            virtual Result::DocCore* doc() const;

            /**
             * 获取文本内容.
             *
             * \return
             */
            virtual QString toString() const;

        private:
            QString value_store;
            int row_store, col_store;
            Result::DesNode *desnode_store;
            Result::DocCore *docpresent_store;
        };

        /**
         * 描述性的节点，如文本节点和引用节点.
         */
        class DesNode
        {
        public:
            virtual ~DesNode() = default;

            /**
             * 节点树深度，根节点深度为0
             *
             * \return
             */
            virtual int depth() const = 0;
            /**
             * 承载文档源实例.
             *
             * \return
             */
            virtual DocCore* document() const = 0;

            /**
             * 类型标记.
             *
             * \return 标记值
             */
            virtual int typeValue() const = 0;

            /**
             * 获取该节点的父节点.
             *
             * \return 父节点实例
             */
            virtual DesNode* parent() const = 0;

            /**
             * 添加子节点
             *
             * \param ins 节点实例
             */
            virtual void appendChild(DesNode *ins) = 0;

            /**
             * 获取所有子节点
             *
             * \return 子节点集合
             */
            virtual QList<DesNode*> children() const = 0;

            /**
             * 检查项目错误.
             *
             * \return true，没有错误
             */
            virtual bool check(QList<QString> &reasons) const = 0;

            /**
             * 返回本节点的代表文本内容.
             *
             * \return 文本内容
             */
            virtual QString toString() const = 0;
        };


        /**
         * 声明描述节点.
         */
        class NamedNode : public  Result::DesNode
        {
        public:
            virtual ~NamedNode() = default;

            /**
             * 获取此节点的名称.
             *
             * \return 名称字符串
             */
            virtual QString name() const = 0;

        };

        /**
         * 文档实例.
         */
        class DocCore
        {
        public:
            explicit DocCore(ProjectCore* core, const QString &path);
            virtual ~DocCore() = default;

            /**
             * 无法识别的节点归并.
             *
             * \return
             */
            Result::DesNode* unknowns() const;

            /**
             * 项目实例.
             *
             * \return
             */
            ProjectCore* project() const;

            /**
             * 重命名指向文件.
             *
             * \param new_name 新路径
             */
            void rename(const QString &new_name);

            /**
             * 源文件路径.
             *
             * \return
             */
            QString filePath() const;

            /**
             * 文件名.
             *
             * \return
             */
            QString fileName() const;

            /**
             * 清除所有的词语节点和内容节点.
             */
            void clear();

            /**
             * 对文档实例添加节点实例.
             *
             * \param ins 节点实例
             * \return 0 - 添加成功
             */
            int append(Words *ins);


            /**
             * 通过位置获取词语.
             *
             * \param row 行位置
             * \param col 列位置
             * \return 字符号
             */
            Words* getWords(int row, int col) const;

        private:
            Result::DesNode *const unknown_host;
            ProjectCore *const core_store;
            QString file_path_store;
            QList<Words*> nodes_store;
        };

        /**
         * 项目实例.
         */
        class ProjectCore
        {
        private:
            QString name_store;

        public:
            explicit ProjectCore(const QString &name);
            virtual ~ProjectCore();

            /**
             * 获取文档内存实例，如果不存在指定实例，则新建实例.
             *
             * \param file_path 文档路径
             * \return 实例
             */
            virtual Parse::Result::DocCore* queryDocument(const QString &file_path) const;
            virtual void replaceDocument(Parse::Result::DocCore *ins);

            virtual Parse::Result::DesNode* queryChain(const QString & name) const;
            virtual Parse::Result::DesNode* queryPoint(Parse::Result::NamedNode* chain, const QString &name) const;

            virtual Parse::Result::DesNode* queryUnit(const QString &name) const;
            virtual Parse::Result::DesNode* queryFragment(Parse::Result::NamedNode *unit, const QString &name) const;

            /**
             * 查询指定顺序下的节点序列.
             *
             * \param type 序列名称
             * \param unit 指定单元下的序列，nullptr代表全局范围
             * \return
             */
            virtual QList<Parse::Result::NamedNode*> queryFragmentsOrderby(const QString &type, Parse::Result::NamedNode* unit = nullptr) const;

        };


    }
}

namespace Syntax {


    /**
     * 解析结果标志.
     */
    enum class ParseResult
    {
        SelfManipulate = 1,
        EnterNext = 2,
        Completed = 3,
        Failed = 4,
    };

    /**
     * 解析器接口.
     */
    class SyntaxParser
    {
    public:
        virtual ~SyntaxParser() = default;

        /**
         * 设置当前活动的Doc实例.
         *
         * \param ins
         */
        virtual void docActive(Parse::Result::DocCore *ins) = 0;

        /**
         * 当前指向的文档.
         *
         * \return 文档实例
         */
        virtual Parse::Result::DocCore* docRef() const = 0;
        /**
         * 适配当前解析.
         *
         * \param seqs
         * \return
         */
        virtual bool applied(const QList<Lex::LexResult>& seqs) = 0;

        /**
         * 重置解析器
         */
        virtual void reset() = 0;

        /**
         * 针对性的解析当前Token序列，对已经解析过的序列做摘除处理，返回下一步可能用到的解析器列表。
         *
         * \param seqs 标记序列
         * \param next_ps 下一步需要用到的解析器
         * \return 解析操作类型
         */
        virtual ParseResult parse(QList<Lex::LexResult>& seqs)= 0;

        /**
         * 子解析器集合.
         *
         * \return
         */
        virtual QList<SyntaxParser*> children() const = 0;

        /**
         * 当前聚焦的节点.
         *
         * \return
         */
        virtual Parse::Result::DesNode* currNode() const = 0;

    public:
        /**
         * 设置子元素解析器，内部元素解析器集合.
         *
         * \param parsers 解析器集合
         */
        virtual void addChild(QList<SyntaxParser*> parsers) = 0;
    };
}
