#pragma once

#include "abstract.h"

#include <util/folder/path.h>
#include <util/system/event.h>

namespace NSaas {

    class TDistributedLock : public TAbstractLock {
    public:
        virtual ~TDistributedLock() override;
        virtual bool IsLocked() const override {
            return IsLocked_;
        }

        static TAbstractLock::TPtr Create(const IVersionedStorage& storage, const TString& id, bool writeLock, const TDuration& timeout, const TDistributedLockOptions& config);

    private:
        class TRenewer;

    private:
        TDistributedLock(const IVersionedStorage& storage, const TString& id, bool writeLock, const TDistributedLockOptions& config);
        bool WaitLocked(TInstant deadline);
        void TryLock();
        bool Renew();
        bool Renew(i64 snapshot, TString& newLockName);
        bool CreateCandidate();
        void RemoveCandidate(const TString& name, const char* comment, ui64 line) const;
        inline TFsPath GetCandidatesPath() const {
            return Path / "candidates";
        }
        void GiveUp();
        void CheckDeprecated();
        const IVersionedStorage& Storage;
        TString Id;
        TFsPath Path;
        TString LockName;
        bool IsLocked_;
        bool WriteLock;
        TManualEvent LockedEvent;
        TDistributedLockOptions Config;
    };

}
