#pragma once

#include <saas/library/storage/zoo/zoo_storage.h>
#include <saas/library/storage/abstract.h>

#include <saas/api/indexing_client/client.h>

#include <util/datetime/base.h>
#include <util/system/rwlock.h>

namespace NMetaProtocol {
    class TDocument;
    class TReport;
}

namespace NSaas {

    class TRTYStorage: public IVersionedStorage {
    private:
        THolder<IVersionedStorage> ZooStorage;
        mutable NSaas::TIndexingClient IndexingClient;

    private:
        bool SendRequest(const TString& request, NMetaProtocol::TReport& report) const;
        ui32 ReadReply(const TString& query, TString& result) const;
        bool GetKeyData(const TString& key, NMetaProtocol::TDocument& doc, i64 version, bool fullData, bool contentOnly = true) const;
        NSaas::TSendResult SendAction(const NSaas::TAction& action) const;
        bool RemoveNodeImpl(const TString& pkey) const;

    protected:
        TAbstractLock::TPtr NativeWriteLockNode(const TString& path, TDuration timeout = TDuration::Seconds(100000)) const override {
            return ZooStorage->WriteLockNode(path, timeout);
        }

        TAbstractLock::TPtr NativeReadLockNode(const TString& path, TDuration timeout = TDuration::Seconds(100000)) const override {
            return ZooStorage->ReadLockNode(path, timeout);
        }

    public:
        TRTYStorage(const IVersionedStorage::TOptions& options);
        virtual bool GetVersion(const TString& key, i64& version) const override;
        bool RemoveNode(const TString& key, bool withHistory = false) const override;
        bool ExistsNode(const TString& key) const override;
        virtual bool GetValue(const TString& key, TString& result, i64 version = -1, bool lock = true) const override;
        virtual bool SetValue(const TString& key, const TString& value, bool storeHistory = true, bool lock = true, i64* version = nullptr) const override;
        bool GetNodes(const TString& key, TVector<TString>& result, bool withDirs = false) const override;
        virtual bool CreatePersistentSequentialNode(const TString& key, const TString& data) const override {
            return SetValue(key + Sprintf("%010lu", Now().MilliSeconds() % 1000000000), data, false);
        }
        static IVersionedStorage::TFactory::TRegistrator<TRTYStorage> Registrator;
    };

}
