#pragma once

#include <util/generic/map.h>
#include <util/generic/hash.h>
#include <util/generic/string.h>
#include <library/cpp/regex/pcre/regexp.h>
#include <util/generic/ptr.h>
#include <util/system/mutex.h>
#include <util/folder/path.h>
#include <util/system/file.h>
#include <library/cpp/json/writer/json_value.h>

TString DirDigest(const char *path);

struct TFileHashInfo {
    TString Hash;
    ui64 Size;
};

typedef THashMap<TString, TFileHashInfo> TDirHashInfo;

TDirHashInfo GetDirHashes(const TString& path, const TRegExMatch* filter = nullptr, const TRegExMatch* exclude = nullptr);
TDirHashInfo FilterDirHashes(const TDirHashInfo& hashes, const TRegExMatch* filter = nullptr, const TRegExMatch* exclude = nullptr);

bool DirsAreEqual(const TString& path1, const TString& path2, TMap<TString, TString>& report, TRegExMatch* filter = nullptr, TRegExMatch* exclude = nullptr);
bool CompareHashes(const TDirHashInfo& hashes1, const TDirHashInfo& hashes2, TMap<TString, TString>& report, bool checkInclude1To2 = false);

class TFilesSizeInfo {
private:
    struct TSizeInfo {
        ui64 Size = 0;
        ui64 Count = 0;
    };
    TMap<TString, TSizeInfo> SizesCounts;
    TMutex Mutex;
public:
    TFilesSizeInfo() = default;
    explicit TFilesSizeInfo(const TString& filePath);

    void Merge(const TFilesSizeInfo& info);
    NJson::TJsonValue GetReport(bool isHumanReadable) const;
    ui64 GetTotalSize() const;

protected:
    void AddInfoUnlocked(const TString& fileName, const ui64 size);
};
