#include "inmem_slotchecker_storage.h"

#include <saas/deploy_manager/server/messages/collect_dm_info.h>

namespace {
    const TString NAME = "TLocalSlotCheckerStorage";
}

namespace NRTYDeploy {
    TLocalSlotCheckerStorage::TLocalSlotCheckerStorage(const TDuration& cacheTime)
        : CacheTime(cacheTime)
    {
        RegisterGlobalMessageProcessor(this);
    }

    TLocalSlotCheckerStorage::~TLocalSlotCheckerStorage() {
        UnregisterGlobalMessageProcessor(this);
    }

    ui32 TLocalSlotCheckerStorage::GetSize() const {
        TGuard<TMutex> g(Mutex);
        return Storage.size();
    }

    bool TLocalSlotCheckerStorage::GetValue(const TString& key, NController::TSlotChecker& value) const {
        TGuard<TMutex> g(Mutex);
        CleanupStorageUnsafe();
        auto it = Storage.find(key);
        if (it == Storage.end()) {
            return false;
        }
        value = it->second->Value;
        return true;
    }

    void TLocalSlotCheckerStorage::SetValue(const TString& key, const NController::TSlotChecker& value) {
        TGuard<TMutex> g(Mutex);
        CleanupStorageUnsafe();
        auto it = Storage.find(key);
        if (it != Storage.end()) {
            ExpirationList.erase(it->second->ExpirationListEntry);
            Storage.erase(it);
        }
        TSimpleSharedPtr<TLocalEntry> entry = new TLocalEntry();
        entry->ExpirationTimeMinutes = (GetNow() + CacheTime).Minutes();
        entry->Key = key;
        entry->Value = value;
        entry->ExpirationListEntry = ExpirationList.insert(ExpirationList.end(), entry);
        Storage[key] = std::move(entry);
    }

     void TLocalSlotCheckerStorage::CleanupStorageUnsafe() const {
        if (ExpirationList.empty()) {
            return;
        }
        const ui32 now = GetNow().Minutes();
        while (!ExpirationList.empty()) {
            auto it = ExpirationList.begin();
            if ((*it)->ExpirationTimeMinutes < now) {
                Storage.erase((*it)->Key);
                ExpirationList.pop_front();
            } else {
                break;
            }
        }
    }

    bool TLocalSlotCheckerStorage::Process(IMessage* message) {
        if (TMessageCollectDeployManagerInfo* collectDMInfo = dynamic_cast<TMessageCollectDeployManagerInfo*>(message)) {
            collectDMInfo->Fields["InmemStorageSize"] = GetSize();
            return true;
        }
        return false;
    }

    TString TLocalSlotCheckerStorage::Name() const {
        return NAME;
    }

} // namespace NRTYDeploy
