#pragma once

#include "data_types.hpp"

#include <chrono>

namespace phosphor
{
namespace dbus
{
namespace monitoring
{

/** @class Callback
 *  @brief Callback interface.
 *
 *  Callbacks of any type can be run.
 */
class Callback
{
  public:
    Callback() = default;
    Callback(const Callback&) = delete;
    Callback(Callback&&) = default;
    Callback& operator=(const Callback&) = delete;
    Callback& operator=(Callback&&) = default;
    virtual ~Callback() = default;

    /** @brief Run the callback.
     *  @param[in] ctx - caller context
     *     Context could be Startup or Signal
     *     Startup: Callback is called as part of process startup.
     *     Signal: Callback is called as part of watch condition has been met.
     *
     */
    virtual void operator()(Context ctx) = 0;

    /** @brief Run the callback.
     *  @param[in] ctx - caller context
     *     Context could be Startup or Signal
     *     Startup: Callback is called as part of process startup.
     *     Signal: Callback is called as part of watch condition has been met.
     *  @param[in] msg - The sdbusplus signal message
     */
    virtual void operator()(Context ctx, sdbusplus::message::message& msg){};
};

/** @class Conditional
 *  @brief Condition interface.
 *
 *  Conditions of any type can be tested for true or false.
 */
class Conditional
{
  public:
    Conditional() = default;
    Conditional(const Conditional&) = delete;
    Conditional(Conditional&&) = default;
    Conditional& operator=(const Conditional&) = delete;
    Conditional& operator=(Conditional&&) = default;
    virtual ~Conditional() = default;

    /** @brief Test the condition. */
    virtual bool operator()() = 0;
};

/** @class IndexedConditional
 *  @brief Condition with an index.
 */
class IndexedConditional : public Conditional
{
  public:
    IndexedConditional() = delete;
    IndexedConditional(const IndexedConditional&) = delete;
    IndexedConditional(IndexedConditional&&) = default;
    IndexedConditional& operator=(const IndexedConditional&) = delete;
    IndexedConditional& operator=(IndexedConditional&&) = default;
    virtual ~IndexedConditional() = default;

    explicit IndexedConditional(const PropertyIndex& conditionIndex) :
        Conditional(), index(conditionIndex)
    {
    }

    /** @brief Test the condition. */
    virtual bool operator()() override = 0;

  protected:
    /** @brief Property names and their associated storage. */
    const PropertyIndex& index;
};

/** @class IndexedCallback
 *  @brief Callback with an index.
 */
class IndexedCallback : public Callback
{
  public:
    IndexedCallback() = delete;
    IndexedCallback(const IndexedCallback&) = delete;
    IndexedCallback(IndexedCallback&&) = default;
    IndexedCallback& operator=(const IndexedCallback&) = delete;
    IndexedCallback& operator=(IndexedCallback&&) = default;
    virtual ~IndexedCallback() = default;
    explicit IndexedCallback(const PropertyIndex& callbackIndex) :
        Callback(), index(callbackIndex)
    {
    }

    /** @brief Run the callback. */
    virtual void operator()(Context ctx) override = 0;

  protected:
    /** @brief Property names and their associated storage. */
    const PropertyIndex& index;
};

/** @class GroupOfCallbacks
 *  @brief Invoke multiple callbacks.
 *
 *  A group of callbacks is implemented as a vector of array indices
 *  into an external array  of callbacks.  The group function call
 *  operator traverses the vector of indices, invoking each
 *  callback.
 *
 *  @tparam CallbackAccess - Access to the array of callbacks.
 */
template <typename CallbackAccess>
class GroupOfCallbacks : public Callback
{
  public:
    GroupOfCallbacks() = delete;
    GroupOfCallbacks(const GroupOfCallbacks&) = delete;
    GroupOfCallbacks(GroupOfCallbacks&&) = default;
    GroupOfCallbacks& operator=(const GroupOfCallbacks&) = delete;
    GroupOfCallbacks& operator=(GroupOfCallbacks&&) = default;
    ~GroupOfCallbacks() = default;
    explicit GroupOfCallbacks(const std::vector<size_t>& graphEntry) :
        graph(graphEntry)
    {
    }

    /** @brief Run the callbacks. */
    void operator()(Context ctx) override
    {
        for (auto e : graph)
        {
            (*CallbackAccess::get()[e])(ctx);
        }
    }

  private:
    /** @brief The offsets of the callbacks in the group. */
    const std::vector<size_t>& graph;
};

/** @class ConditionalCallback
 *  @brief Callback adaptor that asssociates a condition with a callback.
 */
template <typename CallbackAccess>
class ConditionalCallback : public Callback
{
  public:
    ConditionalCallback() = delete;
    ConditionalCallback(const ConditionalCallback&) = delete;
    ConditionalCallback(ConditionalCallback&&) = default;
    ConditionalCallback& operator=(const ConditionalCallback&) = delete;
    ConditionalCallback& operator=(ConditionalCallback&&) = default;
    virtual ~ConditionalCallback() = default;
    ConditionalCallback(const std::vector<size_t>& graphEntry,
                        Conditional& cond) :
        graph(graphEntry),
        condition(cond)
    {
    }

    /** @brief Run the callback if the condition is satisfied. */
    virtual void operator()(Context ctx) override
    {
        if (condition())
        {
            (*CallbackAccess::get()[graph[0]])(ctx);
        }
    }

  protected:
    /** @brief The index of the callback to conditionally invoke. */
    const std::vector<size_t>& graph;

    /** @brief The condition to test. */
    Conditional& condition;
};

/** @class DeferrableCallback
 *
 *  Deferrable callbacks wait a configurable period before
 *  invoking their associated callback.
 *
 *  When the callback condition is initially met, start a timer.  If the
 *  condition is tested again before the timer expires and it is not
 *  met cancel the timer.  If the timer expires invoke the associated
 *  callback.
 *
 *  @tparam CallbackAccess - Provide access to callback group instances.
 *  @tparam TimerType - Delegated timer access methods.
 */
template <typename CallbackAccess, typename TimerType>
class DeferrableCallback : public ConditionalCallback<CallbackAccess>
{
  public:
    DeferrableCallback() = delete;
    DeferrableCallback(const DeferrableCallback&) = delete;
    DeferrableCallback(DeferrableCallback&&) = default;
    DeferrableCallback& operator=(const DeferrableCallback&) = delete;
    DeferrableCallback& operator=(DeferrableCallback&&) = default;
    ~DeferrableCallback() = default;

    DeferrableCallback(const std::vector<size_t>& graphEntry, Conditional& cond,
                       const std::chrono::microseconds& delay) :
        ConditionalCallback<CallbackAccess>(graphEntry, cond),
        delayInterval(delay), timer(nullptr)
    {
    }

    void operator()(Context ctx) override
    {
        if (!timer)
        {
            timer = std::make_unique<TimerType>(
                // **INDENT-OFF**
                [ctx, this](auto& source) {
                    this->ConditionalCallback<CallbackAccess>::operator()(ctx);
                });
            // **INDENT-ON**
            timer->disable();
        }

        if (this->condition())
        {
            if (!timer->enabled())
            {
                // This is the first time the condition evaluated.
                // Start the countdown.
                timer->update(timer->now() + delayInterval);
                timer->enable();
            }
        }
        else
        {
            // The condition did not evaluate.  Stop the countdown.
            timer->disable();
        }
    }

  private:
    /** @brief The length to wait for the condition to stop evaluating. */
    std::chrono::microseconds delayInterval;

    /** @brief Delegated timer functions. */
    std::unique_ptr<TimerType> timer;
};

} // namespace monitoring
} // namespace dbus
} // namespace phosphor
