#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;
    explicit 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
