#pragma once

#include "index_updater.h"

#include <util/system/rwlock.h>

class TDeferredUpdatesStorage {
public:
    typedef TDeferredUpdatesStorage *TPtr;

    class IDecoder {
    public:
        virtual ~IDecoder() { }
        virtual bool Decode(const TDocSearchInfo::THash& identifier, const ui32 oldDocId, ui32& docid) const = 0;
    };

    explicit TDeferredUpdatesStorage(const TRTYServerConfig& config);
    ~TDeferredUpdatesStorage();
    void ApplyDeferredUpdates(IIndexUpdater& updater, const IDecoder& decoder);
    void ApplyDeferredUpdates(const TString& indexDirName, TParsedDocument& doc, ui32 docId);
    void RemoveDocs(const TString& indexDirName, const TVector<ui32>& docIds);
    void SaveUpdate(const TString& indexDirName, ui32 docId, TParsedDocument::TPtr document);

    inline bool IsEmpty() {
        return AllUpdates.empty();
    }

private:
    struct TOneIndexStorage;
    THashMap<TString, THolder<TOneIndexStorage>> AllUpdates;
    TRWMutex Mutex;
    const TRTYServerConfig& Config;
};

class TDeferredIndexUpdater : public TIndexUpdater {
public:
    TDeferredIndexUpdater(IIndexController& owner, TDeferredUpdatesStorage::TPtr storage);
    virtual bool UpdateDoc(ui32 docId, const TParsedDocument::TPtr doc) override;
    virtual bool RestoreDoc(ui32 docId, TParsedDocument::TPtr& doc) override;

    void SetDeferredUpdatesStorage(TDeferredUpdatesStorage::TPtr storage);
    TDeferredUpdatesStorage::TPtr GetDeferredUpdatesStorage();

    void ApplyUpdatesAndDropStorage(IIndexUpdater& updater, const TDeferredUpdatesStorage::IDecoder& decoder);
    void RemoveDocs(const TVector<ui32>& docIds);

protected:
    virtual bool UpdateDocNative(ui32 docId, const TParsedDocument::TPtr doc);

private:
    TRWMutex MutexDeferredUpdatesStorage;
    TDeferredUpdatesStorage::TPtr DeferredUpdatesStorage;
    IIndexController& Owner;
};

