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

#ifndef LOTRO_DAT_LIBRARY_DATIO_H
#define LOTRO_DAT_LIBRARY_DATIO_H

#include <utility>
#include "DatOperationResult.h"

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

    class DatFile;

    class SubDirectory;

    class SubFile;

    /*!
     * \brief Модуль ввода/вывода
     * \author Gi1dor
     * \date 30.06.2018
     * Класс для работы с вводом-выводом данных в dat-контейнере. Предоставляет функции чтения/записи данных, а также
     * информацию об основных параметрах dat файла
     * \warning Объекты этого класса не должны создаваться отдельно! Созданием и управлением ими занимается класс DatFile
     */

    class DatIO {
    public:
        DatIO() = delete;
        DatIO(const DatIO &other) = delete;
        DatIO& operator=(const DatIO &other) = delete;
        ~DatIO();

        explicit DatIO(DatFile *datFilePtr);

        DatOperationResult<> Init(const std::string &filename);

        DatOperationResult<> ReadData(BinaryData &data, long long size, long long offset = 0, long long data_offset = 0) const;

        DatOperationResult<> WriteData(const BinaryData &data, long long size, long long offset = 0, long long data_offset = 0);

        DatOperationResult<long long> GetActualDatSize();

        DatOperationResult<std::string> GetFilename();

        void PrintInformaion(FILE* file);

        DatOperationResult<> DeInit();

    private:

        //------------------------------------------------//
        // PRIVATE INIT SECTION
        //------------------------------------------------//

        DatOperationResult<> OpenDatFile();

        DatOperationResult<> ReadSuperBlock();

        //------------------------------------------------//
        // PRIVATE READ-WRITE SECTION
        //------------------------------------------------//

        void UpdateBufferIfNeeded(long long size_to_write);

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

        DatOperationResult<> ModifyFragmentationJournal();

        DatOperationResult<> UpdateHeader();

    private:
        DatFile *dat;
        FILE *file_handler_;
        std::string filename_;

    public:
        long long constant1;
        long long constant2;
        long long file_size;
        long long version1;
        long long version2;
        long long fragmentation_journal_size;
        long long fragmentation_journal_end;
        long long root_directory_offset;
        long long fragmentation_journal_offset;
        long long free_dat_size;

    private:
        long long actual_dat_size_;
        long long elapsed_eof_buffer_;
        const unsigned MAX_EOF_BUFFER = 15 * 1024 * 1024; /// Maximal size of buffer, which is written to the end of dat file to improve write speed of small fragments
    };
}
};
#endif //LOTRO_DAT_LIBRARY_DATIO_H