//
// Created by kikab on 04.06.2018.
//

#ifndef LOTRO_DAT_LIBRARY_DATFILESYSTEM_H
#define LOTRO_DAT_LIBRARY_DATFILESYSTEM_H

#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <utility>
#include <memory>

#include <DatOperationResult.h>
#include <SubFile.h>
#include <SubDirectory.h>

extern "C++" {
namespace LOTRO_DAT {
    class DatFile;
    class BinaryData;
    class SubDirectory;

    class DatFileSystem {

    public:
        DatFileSystem() = delete;
        DatFileSystem(const DatFileSystem &other) = delete;
        DatFileSystem& operator=(const DatFileSystem &other) = delete;
        ~DatFileSystem() = default;

        explicit DatFileSystem(DatFile *datFilePtr);

        DatOperationResult<> Init();

        DatOperationResult<BinaryData> GetFileData(long long file_id, long long int offset);

        DatOperationResult<std::shared_ptr<SubFile>> GetFile(long long file_id);

        DatOperationResult<bool> CheckCorrectSubfile(const std::shared_ptr<SubFile> &file);

        DatOperationResult<> UpdateFileInfo(const SubFile& file);

        void PrintInformaion(FILE* file);

        DatOperationResult<> DeInit();

    private:
        //------------------------------------------------//
        // PRIVATE INIT SECTION
        //------------------------------------------------//

        DatOperationResult<> InitSubFile(long long file_id);

        DatOperationResult<> InitSubDirectory(SubDirectory dir);

        DatOperationResult<> InitAllDirectories();

        DatOperationResult<> InitAllFiles();

        //------------------------------------------------//
        // PRIVATE DEINIT SECTION
        //------------------------------------------------//

        DatOperationResult<> CommitDirectories();

    private:
        DatFile *dat;
        std::set<long long> subfile_pending_update;

        std::map<long long, std::shared_ptr<SubFile> > dictionary_;

        std::unordered_set<long long> visited_subdirectories_offsets_;
        std::unordered_set<long long> visited_subfiles_ids_;

        std::set<SubDirectory, SubDirectory::SubDirectoryOffsetComparator> subdir_init_queue_;
        std::unordered_map<long long, SubFile> subfile_init_queue_;
    };
}
};

#endif //LOTRO_DAT_LIBRARY_DATFILESYSTEM_H