#pragma once

#include <util/digest/fnv.h>
#include <util/generic/hash.h>
#include <util/generic/hash_set.h>
#include <util/generic/string.h>
#include <util/random/random.h>

#include <mapreduce/yt/client/client.h>

#include <robot/library/yt/static/table.h>

#include <wmconsole/version3/wmcutil/log.h>

namespace NWebmaster {
namespace NIks {

using namespace NJupiter;

struct TRandomSampler {
    Y_SAVELOAD_DEFINE(Seed)

    const char *ATTR_RANDOM_SEED = "random_seed";

    TRandomSampler() = default;
    TRandomSampler(ui32 seed)
        : Seed(seed)
    {
    }

    static const TRandomSampler &CInstance() {
        return *Singleton<TRandomSampler>();
    }

    void Load(NYT::IClientBasePtr client, const TString &table) {
        try {
            Seed = GetYtAttr(client, table, ATTR_RANDOM_SEED).AsUint64();
        } catch (yexception &e) {
            LOG_WARN("No random seed, using default=0");
        }
        SetRandomSeed(Seed);
        Seed = RandomNumber(Max<ui32>());
    }

    void SaveNext(NYT::IClientBasePtr client, const TString &table) {
        SetYtAttr(client, table, ATTR_RANDOM_SEED, Seed);
    }

    ui32 GetSeed() const {
        return Seed;
    }

    ui32 GetDigest(const TString &str) const {
        const TString payload = ToString(Seed) + "." + str;
        return FnvHash<ui32>(payload.data(), payload.size());
    }

    float GetFloatDigest(const TString &str) const {
        return static_cast<float>(GetDigest(str)) / static_cast<float>(Max<ui32>());
    }

public:
    ui32 Seed = 0;
};

NYT::TRichYPath DebugPath(const TString &table);
void LoadOwnerCY(NYT::IClientBasePtr client, const TString &source, THashMap<TString, size_t> &ownerCY);
void LoadOwnerCY(NYT::IClientBasePtr client, const TString &source, THashSet<TString> &ownerCY);
void LoadMainMirrorCY(NYT::IClientBasePtr client, const TString &source, THashMap<TString, size_t> &mainMirrorCY);
void LoadOwnersAfterJul21(THashSet<TString> &owners);

} //namespace NIks
} //namespace NWebmaster
