#include "managed_store.hpp"

#include "dbus_utility.hpp"

#include <boost/asio/io_context.hpp>
#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/message/native_types.hpp>

// TODO:: move these to a separate file (future CL when we have more stores):
namespace managedStore
{

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
ManagedObjectStore* managedObjectStore = nullptr;

// TODO:: can ^ be a std::shared_ptr on `static ManagedObjectStore::instance()`
// when we implement graceful shutdowns

void ManagedObjectStore::processDbusResponse(KeyType keyType,
                                             const ValueType& managedValue,
                                             bool isReadThroughRequest)
{
    ValueType value(managedValue);
    std::string keyTypeStr = keyType.toString();

    BMCWEB_LOG_STATEFUL_DEBUG << "Updating store with fresh "
                              << " Object: " << keyTypeStr
                              << " Value: " << value.toString()
                              << " ec: " << value.errorCode.message();

    // Initialize numTimesUsed:
    value.numTimesUsed = 1;
    auto currentObjectIter = managedObjects.find(keyTypeStr);
    if (currentObjectIter != managedObjects.end())
    {
        // preserve the lastUsed:
        value.lastUsed = currentObjectIter->second.lastUsed;
        // preserve the lastUsedAges:
        value.lastUsedAges = currentObjectIter->second.lastUsedAges;
        // preserve the numTimesUsed:
        value.numTimesUsed = currentObjectIter->second.numTimesUsed;
        // an shared / unique pointer) count refreshes:
        value.numRefreshesDone = currentObjectIter->second.numRefreshesDone + 1;
        // count the scheduled refreshes:
        value.numRefreshesScheduled =
            currentObjectIter->second.numRefreshesScheduled;

        BMCWEB_LOG_STATEFUL_DEBUG << "Updating Current Object:"
                                  << " Key: " << keyTypeStr
                                  << " Value: " << value.toString();
    }

    // Avoid queuing a refresh if a Pq entry exists for the key.
    if (!pqEntrySet.contains(keyTypeStr))
    {
        // Queue refresh operation
        pq.push(PriorityQueueEntry(keyType, value.nextRefreshAt));
        // Track pq entry
        pqEntrySet.insert(keyTypeStr);
    }

    // upsert the key:
    managedObjects.insert_or_assign(keyTypeStr, value);

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Updated Object:"
        << " Object: " << keyTypeStr
        << " New: " << managedObjects.find(keyTypeStr)->second.toString();

    // Update pending dbus response count on receiving response.
    this->managedStoreTracker.decrementPendingDbusResponses(
        isReadThroughRequest);

    auto cbMapIter = requestCbMap.find(keyTypeStr);
    if (cbMapIter != requestCbMap.end())
    {
        std::queue<ManagedStoreCb>& cbQueue = cbMapIter->second;
        while (!cbQueue.empty())
        {
            auto callback = cbQueue.front();
            callback(value);
            cbQueue.pop();
        }
        requestCbMap.erase(cbMapIter->first);
    }

    // Finally, call scheduler to queue up next refresh operations.
    scheduleRefresh();
}

void ManagedObjectStore::refreshObject(const KeyType& key,
                                       bool isReadThroughRequest)
{
    auto managedObjectIter = this->managedObjects.find(key.toString());
    if (managedObjectIter != this->managedObjects.end())
    {
        managedObjectIter->second.numRefreshesScheduled += 1;

        BMCWEB_LOG_STATEFUL_DEBUG
            << "refreshObject:"
            << " Key: " << managedObjectIter->first
            << " value: " << managedObjectIter->second.toString();
    }

    switch (key.getManagedType())
    {
        case ManagedType::kManagedObject:
        {
            getManagedObjectsFromDbusService(
                key.serviceName, key.objectPath,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedPropertyMap:
        {
            getManagedPropertiesMapFromDbusService(
                key.serviceName, key.objectPath, key.interface,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedProperty:
        {
            getManagedPropertiesFromDbusService(
                key.serviceName, key.objectPath, key.interface, key.property,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedSubtree:
        {
            getManagedSubtreeFromDbusService(
                key.objectPath, key.treeDepth, key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedSubtreePaths:
        {
            getManagedSubtreePathsFromDbusService(
                key.objectPath, key.treeDepth, key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedAssociatedSubtree:
        {
            getManagedAssociatedSubtreeFromDbusService(
                key.associatedPath, key.objectPath, key.treeDepth,
                key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
        case ManagedType::kManagedAssociatedSubtreePaths:
        {
            getManagedAssociatedSubtreePathsFromDbusService(
                key.associatedPath, key.objectPath, key.treeDepth,
                key.interfaceList,
                [this, self = shared_from_this(), keyType = key,
                 isReadThroughRequest](const ValueType& managedValue) mutable {
                processDbusResponse(std::move(keyType), managedValue,
                                    isReadThroughRequest);
            });
            break;
        }
    }

    // Record a pending refresh operation.
    this->managedStoreTracker.incrementPendingDbusResponses(
        isReadThroughRequest);
}

bool ManagedObjectStore::canScheduleRefresh()
{
    // The timer callback will schedule the next refresh if the scheduler is
    // active.
    if (this->isSchedulerActive)
    {
        return false;
    }

    // Cannot schedule refresh if pending dbus responses reach threshold.
    if (this->managedStoreTracker.countPendingDbusResponses >=
        this->config.pendingDbusResponsesMax)
    {
        BMCWEB_LOG_STATEFUL_DEBUG << "scheduleRefresh: Pending io "
                                  << "threshold reached.";
        return false;
    }

    // Scan the priority queue to pop the entries that are no longer used
    // or can be refreshed instantly to get to a schedulable entry.
    std::chrono::steady_clock::time_point timeNow = clockNow();
    bool canSchedule = false;
    while (!canSchedule && !this->pq.empty())
    {
        const PriorityQueueEntry& pqEntry = pq.top();

        // Get managedStore key to queue refresh of corresponding object in
        // the managedStore.
        const KeyType& managedStoreKey = pqEntry.managedStoreKey;
        const std::string managedStoreKeyStr = managedStoreKey.toString();
        auto managedObjectIter = managedObjects.find(managedStoreKeyStr);

        // the object is no longer tracked:
        if (managedObjectIter == managedObjects.end())
        {
            pq.pop();
            pqEntrySet.erase(managedStoreKeyStr);
            continue;
        }

        ValueType& keyValue = managedObjectIter->second;
        const auto durationSinceUsed = clockSince(keyValue.lastUsed, timeNow);
        bool isRecentlyUsed = durationSinceUsed < this->config.tLRUThreshold;

        BMCWEB_LOG_STATEFUL_DEBUG
            << "SinceUsed:"
            << " Key: " << managedStoreKeyStr << " durationSinceUsed: "
            << clockSinceMilliseconds(keyValue.lastUsed, timeNow)
            << " isRecentlyUsed: " << isRecentlyUsed;
        // LRU Eviction:
        if (!isRecentlyUsed)
        {
            BMCWEB_LOG_STATEFUL_DEBUG << "Since Used: Evict:"
                                      << " Key: " << managedStoreKeyStr;
            managedObjects.erase(managedObjectIter->first);
            pq.pop();
            pqEntrySet.erase(managedStoreKeyStr);
            continue;
        }

        // If the object corresponding to pqEntry was recently refreshed,
        // re-queue the entry to schedule refresh for later point in time.
        if (keyValue.nextRefreshAt > pqEntry.nextRefreshAt)
        {
            BMCWEB_LOG_STATEFUL_DEBUG << "PQ entry recently refreshed: "
                                      << "Re-queue Key: " << managedStoreKeyStr;
            // Remember associated managedStore key before we pop the pq entry.
            const KeyType key = managedStoreKey;
            pq.pop();
            pq.push(PriorityQueueEntry(key, keyValue.nextRefreshAt));
            continue;
        }
        canSchedule = true;
    }
    return canSchedule;
}

void ManagedObjectStore::scheduleRefresh()
{
    if (!this->canScheduleRefresh())
    {
        return;
    }

    BMCWEB_LOG_STATEFUL_DEBUG
        << "scheduleRefresh: " << pq.size() << " Pending dbus responses: "
        << this->managedStoreTracker.countPendingDbusResponses;

    PriorityQueueEntry pqEntry = pq.top();
    pq.pop();

    std::chrono::steady_clock::time_point timeNow = clockNow();

    // Get service name and object path to schedule refresh of the corresponding
    // object in store.
    const KeyType& managedStoreKey = pqEntry.managedStoreKey;
    std::string managedStoreKeyStr = managedStoreKey.toString();

    // Stop tracking the pq entry once it is pop'd from the queue.
    pqEntrySet.erase(managedStoreKeyStr);

    // Set scheduler status to active before scheduling the refresh op to ensure
    // an immediate callback keeps the system in the correct state.
    isSchedulerActive = true;

    // If the refresh needs to be scheduled later in time, we set the timeout
    // based on the time difference between the expected refresh time and
    // current time.
    // NOTE: the expected refresh time is set based on t_ttl.
    const auto timerTimeout =
        std::chrono::duration_cast<std::chrono::milliseconds>(
            pqEntry.nextRefreshAt - timeNow);
    timer.expires_after(timerTimeout);

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Scheduling Refresh after " << timerTimeout.count()
        << " milliseconds. "
        << "ServiceName: " << managedStoreKey.serviceName
        << " ObjectPath: " << managedStoreKey.objectPath.str
        << " Interface: " << managedStoreKey.interface << " Property: "
        << managedStoreKey.property;

    timer.async_wait([this, self = shared_from_this(),
                      managedStoreKey](boost::system::error_code ec) {
        isSchedulerActive = false;
        if (ec == boost::asio::error::operation_aborted)
        {
            BMCWEB_LOG_STATEFUL_ERROR << "Timer operation aborted" << ec;
            return;
        }

        if (ec)
        {
            BMCWEB_LOG_STATEFUL_ERROR << "Async_wait failed" << ec;
            return;
        }
        BMCWEB_LOG_STATEFUL_DEBUG
            << "Refreshing managed object. "
            << "ServiceName: " << managedStoreKey.serviceName
            << " ObjectPath: " << managedStoreKey.objectPath.str
            << " Interface: " << managedStoreKey.interface << " Property: "
            << managedStoreKey.property;
        refreshObject(managedStoreKey);
        scheduleRefresh();
    });
}

void ManagedObjectStore::getProperty(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    GetManagedPropertyCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        dbus::utility::getProperty(keyType.serviceName, keyType.objectPath,
                                   keyType.interface, keyType.property,
                                   std::move(callback));
        return;
    }

    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedProperty.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedProperty.value());
    });
}

void ManagedObjectStore::getAllProperties(
    const std::string& service, const std::string& objectPath,
    const std::string& interface,
    const ManagedObjectStoreContext& requestContext,
    GetManagedPropertyMapCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        sdbusplus::asio::getAllProperties(*crow::connections::systemBus,
                                          service, objectPath, interface,
                                          std::move(callback));
        return;
    }

    KeyType keyType(ManagedType::kManagedPropertyMap, service, objectPath,
                    interface);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedPropertyMap.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedPropertyMap.value());
    });
}

void ManagedObjectStore::getSubTree(
    const std::string& path, int32_t depth,
    const std::vector<std::string>& interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreeResponse& subtree) {
            callback(ec, subtree);
        },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTree", path, depth,
            interfaces);
        return;
    }

    KeyType keyType(ManagedType::kManagedSubtree, path, depth, interfaces);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtree.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtree.value());
    });
}

void ManagedObjectStore::getSubTree(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    this->getSubTree(path, depth, interfaces2, requestContext,
                     std::move(callback));
}

void ManagedObjectStore::getSubTreePaths(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreePathsCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreePathsResponse&
                    subtreePaths) { callback(ec, subtreePaths); },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path, depth,
            interfaces2);
        return;
    }

    KeyType keyType(ManagedType::kManagedSubtreePaths, path, depth,
                    interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtreePaths.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtreePaths.value());
    });
}

void ManagedObjectStore::getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }
    this->getAssociatedSubTree(associatedPath, path, depth, interfaces2,
                               requestContext, std::move(callback));
}

void ManagedObjectStore::getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreeCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreeResponse& subtree) {
            callback(ec, subtree);
        },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
            associatedPath, path, depth, interfaces2);
        return;
    }

    KeyType keyType(ManagedType::kManagedAssociatedSubtree, associatedPath.str,
                    path.str, depth, interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtree.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtree.value());
    });
}

void ManagedObjectStore::getAssociatedSubTreePaths(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const ManagedObjectStoreContext& requestContext,
    GetManagedSubtreePathsCb&& callback)
{
    std::vector<std::string> interfaces2;
    for (auto& s : interfaces)
    {
        interfaces2.emplace_back(s);
    }

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        crow::connections::systemBus->async_method_call(
            [callback{std::move(callback)}](
                const boost::system::error_code& ec,
                const dbus::utility::MapperGetSubTreePathsResponse&
                    subtreePaths) { callback(ec, subtreePaths); },
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
            associatedPath, path, depth, interfaces);
        return;
    }

    KeyType keyType(ManagedType::kManagedAssociatedSubtreePaths,
                    associatedPath.str, path.str, depth, interfaces2);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (!valueType.managedSubtreePaths.has_value())
        {
            callback(valueType.errorCode, {});
            return;
        }
        callback(valueType.errorCode, valueType.managedSubtreePaths.value());
    });
}

void ManagedObjectStore::getManagedObjects(
    const std::string& service, const sdbusplus::message::object_path& path,
    GetManagedObjectsCb&& callback)
{
    BMCWEB_LOG_STATEFUL_DEBUG << "getManagedObjects:"
                              << " service: " << service
                              << " path: " << path.str;
    // std::shared_ptr<bmcweb::AsyncResp> resp;
    ManagedObjectStoreContext context(nullptr);
    getManagedObjectsWithContext(service, path, context, std::move(callback));
}

void ManagedObjectStore::getManagedObjectsWithContext(
    const std::string& service, const sdbusplus::message::object_path& path,
    const ManagedObjectStoreContext& requestContext,
    GetManagedObjectsCb&& callback)
{
    // total counter of calls:
    this->managedStoreTracker.countGetManagedObjects += 1;

    BMCWEB_LOG_STATEFUL_DEBUG
        << "getManagedObjectsWithContext:"
        << " service: " << service << " path: " << path.str
        << " requestContext: " << requestContext.toString()
        << " count: " << this->managedStoreTracker.countGetManagedObjects;

    // When Object Store is disabled, the requests read through.
    if (!this->isEnabled())
    {
        // TODO:: do we want to count that (if the cache is actually disabled)
        // i think we should since we want to use that as validation for the
        // store being enabled?
        this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;
        dbus::utility::getManagedObjects(service, path, std::move(callback));
        return;
    }

    KeyType keyType(ManagedType::kManagedObject, service, path.str);
    getManagedObjectsInStore(
        keyType, requestContext,
        [callback{std::move(callback)}](const ValueType& valueType) {
        if (valueType.managedObject.has_value())
        {
            callback(valueType.errorCode, valueType.managedObject.value());
            return;
        }
        callback(valueType.errorCode, {});
    });
}

void ManagedObjectStore::getManagedObjectsInStore(
    const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
    ManagedStoreCb&& callback)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "getManagedObjectsInStore:"
        << " service: " << keyType.serviceName
        << " path: " << keyType.objectPath.str << " interface: "
        << keyType.interface << " property: " << keyType.property
        << " requestContext: " << requestContext.toString();

    // Execute callback immidiately if object is cached in store.
    std::string keyTypeStr = keyType.toString();
    auto managedObjectIter = managedObjects.find(keyTypeStr);
    if (managedObjectIter != managedObjects.end())
    {
        ValueType& mappedValueInStore = managedObjectIter->second;
        const std::chrono::steady_clock::time_point timeNow = clockNow();
        const auto currentAge =
            clockSince(mappedValueInStore.lastRefreshAt, timeNow);

        // update lastUsed:
        mappedValueInStore.lastUsed = timeNow;
        // count number of times used:
        mappedValueInStore.numTimesUsed += 1;
        // update lastUsedAges:
        if (!mappedValueInStore.lastUsedAges)
        {
            mappedValueInStore.lastUsedAges = std::make_shared<
                std::list<std::chrono::steady_clock::duration>>();
        }
        mappedValueInStore.lastUsedAges->push_back(currentAge);
        while (mappedValueInStore.lastUsedAges->size() >=
               mappedValueInStore.kLastUsedAgesMaxSize)
        {
            mappedValueInStore.lastUsedAges->pop_front();
        }

        BMCWEB_LOG_STATEFUL_DEBUG
            << "ManagedObject found in store. "
            << " service: " << keyType.serviceName
            << " path: " << keyType.objectPath.str << " interface: "
            << keyType.interface << " property: " << keyType.property
            << " CurrentAge: " << clockDurationMilliseconds(currentAge)
            << " Context: " << requestContext.toString()
            << " Value: " << mappedValueInStore.toString();

        // check if the current object is stale:
        const bool isObjectStale = currentAge >= (this->config.tfixedThreshold +
                                                  this->config.tgraceThreshold);

        // can we use it as is:
        bool isUseCurrentObject = !isObjectStale;

        if (requestContext.hintMaxAge > std::chrono::seconds(0))
        {
            // we have to refresh it because of hintMaxAge
            isUseCurrentObject = (currentAge <= requestContext.hintMaxAge);
            this->managedStoreTracker.countGetManagedObjectsCacheMissMaxAge +=
                1;
            BMCWEB_LOG_STATEFUL_DEBUG
                << "apply:"
                << " hintMaxAgeMS: "
                << clockDurationMilliseconds(requestContext.hintMaxAge);
        }

        // Return if the object is still fresh.
        if (isUseCurrentObject)
        {
            this->managedStoreTracker.countGetManagedObjectsCacheHit += 1;
            callback(mappedValueInStore);
            return;
        }

        // Evict the object from store as it has became stale.
        if (isObjectStale)
        {
            BMCWEB_LOG_ALWAYS
                << "Object has become stale! "
                << " service: " << keyType.serviceName
                << " path: " << keyType.objectPath.str << " interface: "
                << keyType.interface << " property: " << keyType.property
                << " CurrentAge: " << clockDurationMilliseconds(currentAge)
                << " Context: " << requestContext.toString()
                << " Value: " << mappedValueInStore.toString();
            managedObjects.erase(managedObjectIter->first);
        }
    }

    BMCWEB_LOG_STATEFUL_DEBUG
        << "Fetching fresh object over dbus. "
        << " Key: " << keyType.toString()
        << " requestContext: " << requestContext.toString();

    // Handle concurrent requests for the same object by storing callback
    // for the request.
    auto cbMapIter = requestCbMap.find(keyTypeStr);
    if (cbMapIter != requestCbMap.end())
    {
        // Since a request has already read through, any subsequent request
        // will not read through. The callback for these duplicate requests
        // will be stored and invoked when the first request gets a response
        // from dbus.
        cbMapIter->second.push(std::move(callback));
        return;
    }
    requestCbMap[keyTypeStr].push(std::move(callback));

    this->managedStoreTracker.countGetManagedObjectsCacheMiss += 1;

    // Note: This refresh operation is not rate limited i.e all incoming
    // requests with cache-miss will continue to read through without a cap on
    // pending i/o since we don't want to block on scheduler or send a failure
    // response.
    refreshObject(keyType, true);
}

void ManagedObjectStore::clearAllObjects()
{
    this->managedObjects.clear();
    // looks like it's the only way to do this:
    this->pq = ManagedStorePriorityQueue();
}

void ManagedObjectStore::getManagedObjectsFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    ManagedStoreCb&& callback)
{
    dbus::utility::getManagedObjects(
        service, path,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& objects) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(objects, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    });
}

void ManagedObjectStore::getManagedPropertiesFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, const std::string& property,
    ManagedStoreCb&& callback)
{
    dbus::utility::getProperty(
        service, path, interface, property,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DbusVariantType& propertyValue) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(propertyValue, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
        });
}

void ManagedObjectStore::getManagedPropertiesMapFromDbusService(
    const std::string& service, const sdbusplus::message::object_path& path,
    const std::string& interface, ManagedStoreCb&& callback)
{
    sdbusplus::asio::getAllProperties(
        *crow::connections::systemBus, service, path.str, interface,
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DBusPropertiesMap& propertyMap) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(propertyMap, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    });
}

// Calls into dbus service to get subtree.
void ManagedObjectStore::getManagedSubtreeFromDbusService(
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtree, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree", path.str, depth,
        interfaces);
}

// Calls into dbus service to get subtree paths.
void ManagedObjectStore::getManagedSubtreePathsFromDbusService(
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtreePaths, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", path.str, depth,
        interfaces);
}

// Calls into dbus service to get subtree.
void ManagedObjectStore::getManagedAssociatedSubtreeFromDbusService(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtree, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTree",
        associatedPath, path, depth, interfaces);
}

// Calls into dbus service to get subtree paths.
void ManagedObjectStore::getManagedAssociatedSubtreePathsFromDbusService(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    const std::vector<std::string>& interfaces, ManagedStoreCb&& callback)
{
    crow::connections::systemBus->async_method_call(
        [this, self = shared_from_this(), callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
        std::chrono::steady_clock::time_point timeNow = clockNow();
        ValueType value(subtreePaths, ec, timeNow,
                        timeNow + this->config.tfixedThreshold);
        callback(value);
    },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetAssociatedSubTreePaths",
        associatedPath, path, depth, interfaces);
}

std::string ManagedObjectStoreConfig::toString() const
{
    return this->toJson().dump();
}

nlohmann::json ManagedObjectStoreConfig::toJson() const
{
    nlohmann::json obj;
    obj["is_enabled"] = this->isEnabled;
    obj["pendingDbusResponsesMax"] = this->pendingDbusResponsesMax;
    obj["tfixedThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tfixedThreshold);
    obj["tgraceThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tgraceThreshold);
    obj["tLRUThresholdMilliseconds"] =
        clockDurationMilliseconds(this->tLRUThreshold);
    return obj;
}

} // namespace managedStore
