#pragma once

#include <saas/rtyserver/factors/factors_mask.h>

#include <kernel/web_factors_info/factors_gen.h>

#include <util/system/rwlock.h>

namespace NRTYFactors {
    class TConfig;
    class TRankModelHolder;
    using TUsedFactors = TSet<ui32>;
}

namespace NRTYServer {
    struct TFactorMasks {
        TCombinedFactorMask DynamicMask { false };
        NRTYFactors::TFactorChunks DynamicChunks;
        NRTYFactors::TRTYFactorMask RTYMask;
    };
}

class TFactorsMaskCache {
public:
    TFactorsMaskCache(const NRTYFactors::TConfig& config);

    const NRTYServer::TFactorMasks& Get(
        const NRTYFactors::TRankModelHolder* rankModel,
        const NRTYFactors::TRankModelHolder* filterModel,
        const NRTYFactors::TFactorSet* factorSet,
        const NRTYFactors::TUsedFactors* extraFactors
    ) const;

    const NRTYServer::TFactorMasks& GetAll() const {
        return AllFactorsMasks;
    }

private:
    using TFactorsMaskHash = ui64;

private:
    TFactorsMaskHash FactorHash(const TString& modelName) const;
    TFactorsMaskHash FactorHash(const NRTYFactors::TUsedFactors& factors) const;
    NRTYServer::TFactorMasks CalculateMasks(const NRTYFactors::TUsedFactors& factors) const;
    TCombinedFactorMask CalculateDynamicFactorsMask(const NRTYFactors::TUsedFactors& factors) const;
    NRTYFactors::TFactorChunks CalculateDynamicFactorsChunks(const NRTYFactors::TUsedFactors& factors) const;
    NRTYFactors::TRTYFactorMask CalculateRTYFactorMask(const NRTYFactors::TUsedFactors& factors) const;

private:
    const NRTYFactors::TConfig& Config;

    mutable THashMap<TFactorsMaskHash, NRTYServer::TFactorMasks> Storage;
    NRTYServer::TFactorMasks AllFactorsMasks;
    TRWMutex Lock;
};
