#pragma once

#include <saas/rtyserver/common/common_rty.h>
#include <saas/rtyserver/indexer_core/abstract_model.h>

#include <util/generic/singleton.h>

#include <array>

class IRTYErfManager;
class TDDKComponentConfig;

namespace NRTYServer {
    class IIndexManagersStorage;
}

class TRTYDDKManager final
    : public IDDKManager
    , public IUrlIdInfo
    , public NRTYServer::IIndexComponentManager
{
public:
    TRTYDDKManager(TAutoPtr<IRTYErfManager> base, const TDDKComponentConfig& config);
    TRTYDDKManager(IRTYErfManager* base, const TDDKComponentConfig& config);
    TRTYDDKManager(IRTYErfManager* base, const TDDKComponentConfig& config, bool useUrlIdHash);
    ~TRTYDDKManager();

    bool RemapRequired() const;

    const TDDKComponentConfig& GetConfig() const {
        return Config;
    }

    const IRTYErfManager* GetBase() const {
        return Base;
    }
public: // IDDKManager
    const IUrlIdInfo* GetUrlIdInfo() const override {
        return this;
    }

    bool CheckDeadLine(ui32 docId, ui32 currentTimeMinutes) const override;
    void MarkForDelete(ui32 docId, ui32 marker) const override;
    void UpdateVersion(ui32 docId, ui32 version) const override;
    void UpdateTimestamp(ui32 docId, ui32 timestamp) const override;
    void UpdateVersionWithTimestamp(ui32 docId, ui32 version, ui32 timestamp) const override;

    ui32 GetSourceWithNewVersion(ui32 docId) const override;
    ui32 GetVersion(ui32 docId) const override;
    ui32 GetTimeLiveStart(ui32 docId) const override;
    ui32 GetParsedEntitiesHash(ui32 docId) const override;
    ui32 GetDeadlineIfEnabled(ui32 docId) const override;
    ui32 GetDeadline(ui32 docId) const override;
    ui16 GetStreamId(ui32 docId) const override;

    TDocSearchInfo::THash GetIdentifier(ui32 docId) const override;

    ui64 GenerateUrlIdHash(const TDocSearchInfo& searchInfo) const override;

    bool IsDeadlineEnabled() const override;
    bool IsReadOnly() const override;

public: // IUrlIdInfo
    ui64 GetUrlId(ui32 docId) const override;

public: // NRTYServer::IIndexComponentManager
    bool DoOpen() override;
    bool DoClose() override;
    ui32 GetDocumentsCount() const override;
    void GetExportedFunctions(NRTYFeatures::TImportedFunctionsBuilder& exports) const override;
    void InitInteractions(const NRTYServer::IIndexManagersStorage& storage) override;
    bool GetDocInfo(const ui32 docId, NJson::TJsonValue& result) const override;
    bool UpdateDoc(ui32 docId, const TParsedDocument::TPtr doc) override;
    ui32 RemoveDocids(const TVector<ui32>& docids) override;
    ui32 MarkDocIdsForDeleteUnsafe(const TVector<ui32>& docids, ui32 marker) override;
    ERTYSearchResult DoSearch(const TRTYSearchRequestContext& /*context*/, ICustomReportBuilder& /*reportBuilder*/, const IIndexController& /*controller*/) const override;

protected:
    template <class T, size_t Index>
    inline T GetField(ui32 docId, T defaultValue = Default<T>()) const;

    template <size_t Index>
    inline ui16 GetField(ui32 docId, ui16 defaultValue = Default<ui16>()) const;

    template <class F>
    inline void Update(ui32 docId, F function) const;

    ui64 GenerateUrlIdHash(const TDocSearchInfo::THash& hash) const;
    ui64 GenerateUrlIdHash(ui32 docId) const;

protected:
    THolder<IRTYErfManager> BaseHolder;
    IRTYErfManager* Base;
    const TDDKComponentConfig& Config;
    const bool IsStatic;
    const bool UseUrlIdHash;

    static constexpr size_t PatchMutexCount = 16;

    TVector<ui64> UrlIdHashes;
    std::array<TMutex, PatchMutexCount> PatchMutex;
};
