#pragma once
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include "callback.hpp"
#include <sdbusplus/exception.hpp>
#include <experimental/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::experimental::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
    {
        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.empty() && any_ns::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(any_ns::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
