#pragma once

#include "dbus_utility.hpp"
#include "managed_store_types.hpp"

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

#include <unordered_set>

namespace managedStore
{

// forward declaration:
class ManagedObjectStoreHttp;

// ManagedObjectStore caches all responses to GetManagedObjects in memory.
// This store aims to provide O(1) access to ManagedObjectType objects to save
// the round trip latency to query data from each DBus connection.
// A background async task using boost::asio::steady_timer ensures freshness of
// managed objects in store.
class ManagedObjectStore :
    public std::enable_shared_from_this<ManagedObjectStore>
{
  public:
    friend class ManagedObjectStoreHttp;

    explicit ManagedObjectStore(const ManagedObjectStoreConfig& cfg,
                                boost::asio::io_context& io) :
        config(cfg),
        timer(io), managedStoreTracker(cfg.pendingDbusResponsesMax)
    {}

    virtual ~ManagedObjectStore() = default;

    using GetManagedObjectsCb =
        std::function<void(const boost::system::error_code&,
                           const dbus::utility::ManagedObjectType&)>;

    using GetManagedPropertyMapCb =
        std::function<void(const boost::system::error_code&,
                           const ::dbus::utility::DBusPropertiesMap&)>;

    using GetManagedPropertyCb =
        std::function<void(const boost::system::error_code&,
                           const dbus::utility::DbusVariantType&)>;

    using GetManagedSubtreeCb =
        std::function<void(const boost::system::error_code&,
                           const dbus::utility::MapperGetSubTreeResponse&)>;

    using GetManagedSubtreePathsCb = std::function<void(
        const boost::system::error_code&,
        const dbus::utility::MapperGetSubTreePathsResponse&)>;

    // Callback used to move managed objects/properties within the store.
    // This allows the store to operate on ValueType instead of specific
    // dbus::utility::DbusVariantType, dbus::utility::ManagedObjectType.
    using ManagedStoreCb = std::function<void(const ValueType&)>;

    // Maps ManagedStore key to request callback.
    using ManagedStoreCallbackMap =
        std::unordered_map<std::string, std::queue<ManagedStoreCb>>;

    // Tracks all entries in PQ to prevent redundant refresh requests to queue
    // up.
    using ManagedStorePqEntrySet = std::unordered_set<std::string>;

    // call getManagedObjectsWithContext with a default context
    void getManagedObjects(const std::string& service,
                           const sdbusplus::message::object_path& path,
                           GetManagedObjectsCb&& callback);

    void getAllProperties(const std::string& service,
                          const std::string& objectPath,
                          const std::string& interface,
                          const ManagedObjectStoreContext& requestContext,
                          GetManagedPropertyMapCb&& callback);

    void getSubTree(const std::string& path, int32_t depth,
                    std::span<const std::string_view> interfaces,
                    const ManagedObjectStoreContext& requestContext,
                    GetManagedSubtreeCb&& callback);

    void getSubTree(const std::string& path, int32_t depth,
                    const std::vector<std::string>& interfaces,
                    const ManagedObjectStoreContext& requestContext,
                    GetManagedSubtreeCb&& callback);

    void getSubTreePaths(const std::string& path, int32_t depth,
                         std::span<const std::string_view> interfaces,
                         const ManagedObjectStoreContext& requestContext,
                         GetManagedSubtreePathsCb&& callback);

    void 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);

    void 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);

    void 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);

    ManagedStoreTracker getStoreTracker() const
    {
        return this->managedStoreTracker;
    }

    // call the 'callback' with cached/fetched object
    void getManagedObjectsWithContext(
        const std::string& service, const sdbusplus::message::object_path& path,
        const ManagedObjectStoreContext& requestContext,
        GetManagedObjectsCb&& callback);

    // call the 'callback' with cached/fetched property
    void getProperty(const KeyType& keyType,
                     const ManagedObjectStoreContext& requestContext,
                     GetManagedPropertyCb&& callback);

    // check if the store is enabled:
    bool isEnabled() const
    {
        return config.isEnabled;
    }

    // get the current config
    const ManagedObjectStoreConfig& getConfig() const
    {
        return config;
    }

    // protected APIs (SPI):
  protected:
    // clear/flush all managed objects:
    void clearAllObjects();

    // Calls into dbus service to get managed objects.
    // Virtual to allow unit testing and possible derived implementations of
    // managedStore.
    virtual void getManagedObjectsFromDbusService(
        const std::string& service, const sdbusplus::message::object_path& path,
        ManagedStoreCb&& callback);

    // Calls into dbus service to get managed properties.
    virtual void getManagedPropertiesFromDbusService(
        const std::string& service, const sdbusplus::message::object_path& path,
        const std::string& interface, const std::string& property,
        ManagedStoreCb&& callback);

    // Calls into dbus service to getAllProperties.
    virtual void getManagedPropertiesMapFromDbusService(
        const std::string& service, const sdbusplus::message::object_path& path,
        const std::string& interface, ManagedStoreCb&& callback);

    // Calls into dbus service to get subtree.
    virtual void getManagedSubtreeFromDbusService(
        const sdbusplus::message::object_path& path, int32_t depth,
        const std::vector<std::string>& interfaces, ManagedStoreCb&& callback);

    // Calls into dbus service to get subtree paths.
    virtual void getManagedSubtreePathsFromDbusService(
        const sdbusplus::message::object_path& path, int32_t depth,
        const std::vector<std::string>& interfaces, ManagedStoreCb&& callback);

    virtual void getManagedAssociatedSubtreeFromDbusService(
        const sdbusplus::message::object_path& associatedPath,
        const sdbusplus::message::object_path& path, int32_t depth,
        const std::vector<std::string>& interfaces, ManagedStoreCb&& callback);

    virtual void getManagedAssociatedSubtreePathsFromDbusService(
        const sdbusplus::message::object_path& associatedPath,
        const sdbusplus::message::object_path& path, int32_t depth,
        const std::vector<std::string>& interfaces, ManagedStoreCb&& callback);

  private:
    // schedule the next refresh event (timer):
    void scheduleRefresh();

    // Checks all the invariants for scheduling a refresh operation.
    // An object can be scheduled for refresh if:
    //  1) The object can be fetched from queue i.e queue is not empty
    //  2) The object is tracked in managedObjects.
    //  3) The object is not overdue for a refresh (refresh the object
    //     instantly in that case)
    //  4) The object was last used within tLRUThreshold time.
    bool canScheduleRefresh();

    // fetch the given object from DBUS:
    // Refresh operation is considered high priority when isReadThroughRequest
    // is set to true i.e the refresh is not subject to the pending i/o
    // threshold invariant.
    void refreshObject(const KeyType& key, bool isReadThroughRequest = false);

    // Process dbus response after refreshObject(), invokes given callback if
    // valid.
    void processDbusResponse(KeyType keyType, const ValueType& managedValue,
                             bool isReadThroughRequest);

    // Get managed entities (properties / objects) from store.
    // Triggers refresh if not in store.
    void getManagedObjectsInStore(
        const KeyType& keyType, const ManagedObjectStoreContext& requestContext,
        ManagedStoreCb&& callback);

    // priority queue of refreshes:
    ManagedStorePriorityQueue pq;

    // Tracks callback for incoming requests.
    ManagedStoreCallbackMap requestCbMap;

    // Tracks all entries in managedStore priority queue.
    ManagedStorePqEntrySet pqEntrySet;

    // Stores ManagedObjectType objects with D-Bus interface and connection as
    // key along with other metadata necessary for scheduling data refresh.
    ManagedObjectsMap managedObjects;

    // runtime config for the store
    ManagedObjectStoreConfig config;

    // A single timer object is used to asynchronously wait for a fixed duration
    // before refreshing ManagedObject in store with the shortest deadline.
    boost::asio::steady_timer timer;

    // Flag set to true when scheduler has scheduled a refresh operation.
    bool isSchedulerActive = false;

    // Tracks state of managed object store.
    ManagedStoreTracker managedStoreTracker;

  protected: // friend (ManagedObjectStoreHttp class would use there)
    // read only list of objects (metrics):
    const std::unordered_map<std::string, ValueType>& getManagedObjects() const
    {
        return managedObjects;
    }

    // read only priority queue of refreshes:
    const ManagedStorePriorityQueue& getPriorityQueue() const
    {
        return pq;
    }

    // Disable copy constructors (singelton)
    ManagedObjectStore(const ManagedObjectStore&) = delete;
    ManagedObjectStore& operator=(const ManagedObjectStore&) = delete;

    // Not yet: https://gbmc-private-review.git.corp.google.com/c/gbmcweb/+/3520
    // ManagedObjectStore(ManagedObjectStore&&) = delete;
    // ManagedObjectStore& operator=(ManagedObjectStore&&) = delete;

    // TODO: use this macro / template ^
    // https://www.boost.org/doc/libs/1_81_0/libs/serialization/doc/singleton.html
};

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

// TODO: this should be a ManagedObjectStore::instance() ^
// TODO: can this be a std::shared_ptr
// TODO:
// https://www.boost.org/doc/libs/1_81_0/libs/serialization/doc/singleton.html

} // namespace managedStore
