#ifndef MANAGER_DOCS_H
#define MANAGER_DOCS_H

#include "DocsManager.h"
#include "route.h"

#include <QTreeView>
#include <QWidget>
#include <libProjectManager.h>
#include <commandsdispatcher.h>

namespace Core {
    class AppCore;
}

namespace MakeTools {
    class FilePresent;
}

namespace Components {

    class HostListener {
      public:
        virtual ~HostListener() = default;

        virtual void hasBeenAccepted(const Core::Route &key) = 0;
        virtual void hasBeenRemoved(const Core::Route &key) = 0;
        virtual void hasBeenClosed(const Core::Route &key) = 0;
    };

    class PresentHost {
      public:
        virtual ~PresentHost() = default;

        /**
         * @brief 承载内容的Widget
         * @return
         */
        virtual QWidget *hostWidget() const = 0;

        /**
         * @brief 添加内容展示实例
         * @param ins
         */
        virtual void append(MakeTools::PresentBase *ins, const Core::Route &key) = 0;
        /**
         * @brief 激活内容展示实例
         * @param ins
         */
        virtual bool active(const Core::Route &key) = 0;
        /**
         * @brief 移除内容展示实例
         * @param ins
         */
        virtual MakeTools::PresentBase *remove(const Core::Route &key) = 0;

        virtual bool instContains(MakeTools::PresentBase *ins) const = 0;

        virtual void setVisibleState(bool state) = 0;
        virtual bool visibleState() const = 0;
    };

} // namespace Components

namespace DataModel {

    /**
     * @brief 文档管理器，根据项目配置文件，打开、查询、关闭文档实例
     */
    class DocumentsManager : public Schedule::AccessibleObject, public Components::HostListener {
      public:
        DocumentsManager(Core::AppCore *src, Project::ProjectManager *project, Components::PresentHost *direct_con);
        virtual ~DocumentsManager() = default;

        Project::ProjectManager* projectManager() const;

        /**
         * @brief 提供完整路径创建新包
         * @param path [/x_name]+
         */
        void newPackage(const Core::Route &link);
        /**
         * @brief 提供父节点Index，创建新包
         * @param group
         * @param name
         * @throw SimpleException
         */
        void newPackage(const Core::Route &group, const QString &name);

        /**
         * @brief 获取支持的文件类型
         * @return {txt, storychain, ……}
         */
        QList<QString> fileTypes() const;
        /**
         * @brief 在指定的包节点下，创建指定类型的新文件
         * @param group 包节点
         * @param name 文件名称
         * @param suffix 通过后缀名，指定文件类型
         * @throw SimpleException
         */
        void newFile(const Core::Route &group_path, const QString &name, const QString &suffix);

        QModelIndex converter(const Core::Route &path);
        Core::Route converter(const QModelIndex &index);

        /**
         * @brief 移除指定节点（必须非根节点）
         * @param node 文件节点或者包节点
         * @throw SimpleException
         */
        void removeNode(const Core::Route &node_path);

        /**
         * @brief 修改指定节点的名称
         * @param node 节点Index
         * @param name 新名称
         * @throw SimpleException
         */
        void renameNode(const Core::Route &node_path, const QString &name);

        /**
         * @brief 打开文件节点
         * @param path_node
         * @throw SimpleException
         */
        void openFile(const Core::Route &path_node);

        /**
         * @brief 获取打开的活跃文档
         * @return
         */
        QList<Core::Route> actives() const;
        /**
         * @brief 获取打开的内容展示实例，如果指向未打开的节点或无效文件节点，返回null
         * @param node
         * @return null或打开的展示实例
         */
        MakeTools::FilePresent* activePresentOf(const Core::Route &node_path);

        /**
         * @brief 保存指定的文档节点集合
         * @param docs
         */
        void save(const QList<Core::Route> &docs = QList<Core::Route>());

        /**
         * @brief 关闭定制的文档节点集合
         * @param docs
         */
        void close(const QList<Core::Route> &doc_paths = QList<Core::Route>());


        /**
         * @brief 查询指定实例（打开的）关联的ModelIndex
         * @param ins
         */
        Core::Route pathOf(MakeTools::FilePresent *ins) const;
        Core::Route pathOf(const QModelIndex &p) const;

        /**
         * @brief 构建所有源代码
         * @param disk
         */
        void build(bool disk);

        // AccessibleObject interface
      public:
        virtual QString name() const override;

        // HostListener interface
      public:
        virtual void hasBeenAccepted(const Core::Route &key) override;
        virtual void hasBeenRemoved(const Core::Route &key) override;
        virtual void hasBeenClosed(const Core::Route &key) override;

      private:
        Core::AppCore *const rtcore;
        Project::ProjectManager *pjtins;
        Components::PresentHost *present_ui;

        QHash<Core::Route, MakeTools::FilePresent *> doc_openning;
        QHash<MakeTools::FilePresent *, std::function<void(const QString &)>> functions_build;
        QHash<MakeTools::FilePresent *, std::function<void(const QString &)>> functions_render;
    };
} // namespace DataModel

#endif // MANAGER_DOCS_H
