#ifndef LIBPARSE_H
#define LIBPARSE_H

#include "libParse_global.h"
#include "ComnDef.h"

#include <QFileInfo>
#include <QList>
#include <QString>

namespace Parse
{
    namespace Result
    {
        class DesNode;
    }

    class ErrorMessage
    {
    public:
        ErrorMessage(const Result::DesNode *obj);

        QString Reason;
        QString Text;
        QString FilePath;
        int CodeRow;
        int CodeCol;

        const Result::DesNode *const object;
    };

    namespace  Result{
        class ParseCore;
        class DocCore;

        enum class DocType
        {
            STORYBOARD  =   DOC_STORYBOARD,
            STORYUNIT   =   DOC_STORYUNIT,
            STORYCHAIN  =   DOC_STORYCHAIN,
            STORYOUTLINES = DOC_VOLUMEOUTLINE,
            STORYCONCEPTS = DOC_STORYCONCEPT
        };

        /**
         * 词语块，可以通过文档未知直接获取.
         */
        class LIBPARSE_EXPORT 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 LIBPARSE_EXPORT DesNode {
          public:
            DesNode(DocCore *core, int type_value, DesNode *pnode = nullptr);
            virtual ~DesNode();

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

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

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

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

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

            /**
             * @brief 注册引用本节点的词语
             * @param ins
             */
            void registerWords(Words *ins);

            /**
             * @brief 获取所有引用本节点的词语
             * @return
             */
            QList<Words*> refered() const;

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

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

        protected:
            void clear_refers();

        private:
            DocCore *const doc_store;
            int type_value;
            DesNode *const parent_node;

            QList<DesNode*> children_nodes;
            QList<Words*> words_collection;
        };

        /**
         * 声明描述节点.
         */
        class LIBPARSE_EXPORT NamedNode : public  Result::DesNode
        {
        public:
            NamedNode(const QString &name, DocCore *core, int type, DesNode *pnode = nullptr);
            virtual ~NamedNode() = default;

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

        private:
            QString name_store;

        };

        /**
         * 文档实例专用于文档高亮渲染和语法补全.
         */
        class LIBPARSE_EXPORT DocCore
        {
        public:
            explicit DocCore(ParseCore* core, DocType type, const QFileInfo &path, const QString &doc_name);
            virtual ~DocCore() = default;

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

            /**
             * 项目实例.
             *
             * \return
             */
            ParseCore* core() const;

            /**
             * @brief 文档类型
             * @return
             */
            DocType docType() const;

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

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

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

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


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

            int append(DesNode *ins);
            QList<DesNode*> syntaxNodes() const;

        private:
            Result::DesNode *const unknown_host;
            ParseCore *const core_store;
            QString doc_name;
            QString file_path_store;
            DocType type_store;

            QList<Words*> words_store;
            QList<DesNode*> root_nodes;
        };

        /**
         * 解析实例核心.
         */
        class LIBPARSE_EXPORT ParseCore
        {
        private:
            QList<DocCore*> doc_nodes;

        public:
            explicit ParseCore();
            virtual ~ParseCore() = default;

            virtual void registerDoc(DocCore *ins);
            virtual QList<DocCore *> allDocuments() const;

            /**
             * 获取文档内存实例，如果不存在指定实例，返回nullptr.
             *
             * \param file_path 文档路径
             * \return 实例
             */
            virtual Result::DocCore* queryDocument(const QFileInfo &file_src) const;
            virtual void deleteDocument(Result::DocCore *ins);
            virtual void clear();

            virtual QList<Result::DesNode*> allStoryChains() const;
            virtual QList<Result::DesNode*> queryStoryChain(const QString & name) const;
            virtual QList<Result::DesNode*> queryStoryPoint(Result::DesNode* chain, const QString &name) const;

            virtual QList<Result::DesNode*> allStoryUnits() const;
            virtual QList<Result::DesNode*> queryStoryUnit(const QString &name) const;
            virtual QList<Result::DesNode*> queryStoryFragment(Result::DesNode *unit, const QString &name) const;
            virtual QList<std::pair<Result::NamedNode*, double>> queryOrdersFragment() const;

            virtual QList<Result::DesNode*> allStoryBoards() const;
            virtual QList<Result::DesNode*> queryStoryBoard(const QString &name) const;
            virtual QList<Result::DesNode*> queryStoryFragmentRefer(Result::DesNode *unit, const QString &name) const;

            virtual QList<Result::DesNode*> allStoryConcept() const;
            virtual QList<Result::DesNode*> queryStoryConcept(const QString &name) const;
            virtual QList<Result::DesNode*> queryStoryStrongPoint(Result::DesNode *concept, const QString &name) const;

            /**
             * @brief 获取卷宗大纲叙述节点
             * @param name
             * @return
             */
            virtual QList<Result::DesNode*> queryStoryDepiction(const QString &name) const;

        };
    }
}

#endif // LIBPARSE_H
