#pragma once
#include "callback.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <sdbusplus/exception.hpp>

#include <experimental/tuple>
#include <string>
#include <tuple>

namespace phosphor
{
namespace dbus
{
namespace monitoring
{

/** @struct ToString
 * @brief Convert numbers to strings
 */
template <typename T>
struct ToString
{
    static auto op(T&& value)
    {
        return std::to_string(std::forward<T>(value));
    }
};

template <>
struct ToString<std::string>
{
    static auto op(const std::string& value)
    {
        return value;
    }
};

/** @class ElogBase
 *  @brief Elog callback implementation.
 *
 *  The elog callback logs the elog and
 *  elog metadata.
 */
class ElogBase : public Callback
{
  public:
    ElogBase(const ElogBase&) = delete;
    ElogBase(ElogBase&&) = default;
    ElogBase& operator=(const ElogBase&) = delete;
    ElogBase& operator=(ElogBase&&) = default;
    virtual ~ElogBase() = default;
    ElogBase() : Callback()
    {}

    /** @brief Callback interface implementation. */
    void operator()(Context ctx) override;

  private:
    /** @brief Delegate type specific calls to subclasses. */
    virtual void log() const = 0;
};

namespace detail
{

/** @class CallElog
 *  @brief Provide explicit call forwarding to phosphor::logging::report.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 */
template <typename T, typename... Args>
struct CallElog
{
    static void op(Args&&... args)
    {
        phosphor::logging::report<T>(std::forward<Args>(args)...);
    }
};

} // namespace detail

/** @class Elog
 *  @brief C++ type specific logic for the elog callback.
 *         The elog callback logs the elog and elog metadata.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 *  @param[in] arguments - Metadata fields to be added to the error log
 */
template <typename T, typename... Args>
class Elog : public ElogBase
{
  public:
    Elog(const Elog&) = delete;
    Elog(Elog&&) = default;
    Elog& operator=(const Elog&) = delete;
    Elog& operator=(Elog&&) = default;
    ~Elog() = default;
    Elog(Args&&... arguments) :
        ElogBase(), args(std::forward<Args>(arguments)...)
    {}

  private:
    /** @brief elog interface implementation. */
    void log() const override
    {
        std::apply(detail::CallElog<T, Args...>::op, std::tuple_cat(args));
    }
    std::tuple<Args...> args;
};

/**
 * @class ElogWithMetadataCapture
 *
 * @brief A callback class that will save the paths, names, and
 *       current values of certain properties in the metadata of the
 *       error log it creates.
 *
 * The intended use case of this class is to create an error log with
 * metadata that includes the property names and values that caused
 * the condition to issue this callback.  When the condition ran, it had
 * set the pass/fail field on each property it checked in the properties'
 * entries in the Storage array.  This class then looks at those pass/fail
 * fields to see which properties to log.
 *
 * Note that it's OK if different conditions and callbacks share the same
 * properties because everything runs serially, so another condition can't
 * touch those pass/fail fields until all of the first condition's callbacks
 * are done.
 *
 * This class requires that the error log created only have 1 metadata field,
 * and it must take a string.
 *
 * @tparam errorType - Error log type
 * @tparam metadataType - The metadata to use
 * @tparam propertyType - The data type of the captured properties
 */
template <typename errorType, typename metadataType, typename propertyType>
class ElogWithMetadataCapture : public IndexedCallback
{
  public:
    ElogWithMetadataCapture() = delete;
    ElogWithMetadataCapture(const ElogWithMetadataCapture&) = delete;
    ElogWithMetadataCapture(ElogWithMetadataCapture&&) = default;
    ElogWithMetadataCapture& operator=(const ElogWithMetadataCapture&) = delete;
    ElogWithMetadataCapture& operator=(ElogWithMetadataCapture&&) = default;
    virtual ~ElogWithMetadataCapture() = default;
    explicit ElogWithMetadataCapture(const PropertyIndex& index) :
        IndexedCallback(index)
    {}

    /**
     * @brief Callback interface implementation that
     *        creates an error log
     */
    void operator()(Context ctx) override
    {
        if (ctx == Context::START)
        {
            // No action should be taken as this call back is being called from
            // daemon Startup.
            return;
        }
        auto data = captureMetadata();

        phosphor::logging::report<errorType>(metadataType(data.c_str()));
    }

  private:
    /**
     * @brief Builds a metadata string with property information
     *
     * Finds all of the properties in the index that have
     * their condition pass/fail fields (get<resultIndex>(storage))
     * set to true, and then packs those paths, names, and values
     * into a metadata string that looks like:
     *
     * |path1:name1=value1|path2:name2=value2|...
     *
     * @return The metadata string
     */
    std::string captureMetadata()
    {
        std::string metadata{'|'};

        for (const auto& n : index)
        {
            const auto& storage = std::get<storageIndex>(n.second).get();
            const auto& result = std::get<resultIndex>(storage);

            if (result.has_value() && std::any_cast<bool>(result))
            {
                const auto& path = std::get<pathIndex>(n.first).get();
                const auto& propertyName =
                    std::get<propertyIndex>(n.first).get();
                auto value = ToString<propertyType>::op(
                    std::any_cast<propertyType>(std::get<valueIndex>(storage)));

                metadata += path + ":" + propertyName + '=' + value + '|';
            }
        }

        return metadata;
    };
};

/** @brief Argument type deduction for constructing Elog instances.
 *
 *  @tparam T - Error log type
 *  @tparam Args - Metadata fields types.
 *  @param[in] arguments - Metadata fields to be added to the error log
 */
template <typename T, typename... Args>
auto makeElog(Args&&... arguments)
{
    return std::make_unique<Elog<T, Args...>>(std::forward<Args>(arguments)...);
}

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