/**
 * @brief SNMP Error Notification class.
 *
 * This file is part of phosphor-snmp project.
 *
 * Copyright (c) 2018 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Note: In near future this file will be autogenerated by the custom parser.
 *
 */

#pragma once

// net-snmp requires a very specific header include order.
// disable clang-format around this block
// clang-format off
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
// clang-format on

#include <sdbusplus/server.hpp>

#include <experimental/any>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>

namespace any_ns = std::experimental;

namespace phosphor
{
namespace network
{
namespace snmp
{

using OID = std::array<oid, MAX_OID_LEN>;
using OID_LEN = size_t;
using Type = u_char;

using Value = std::variant<uint32_t, uint64_t, int32_t, std::string>;
// Generic snmp trap ID
oid SNMPTrapOID[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0};

using Object = std::tuple<OID, OID_LEN, Type, Value>;

/** @brief Get the ASN object type from the given templatized type.
 *         Specialize this template for handling a specific type.
 *  @tparam T - type of object from ASN type would be decided.
 *  @returns the ASN object type.
 */
template <typename T>
u_char getASNType() = delete;

template <>
u_char getASNType<uint32_t>()
{
    return ASN_UNSIGNED;
}

template <>
u_char getASNType<uint64_t>()
{
    return ASN_OPAQUE_U64;
}

template <>
u_char getASNType<int32_t>()
{
    return ASN_INTEGER;
}

template <>
u_char getASNType<std::string>()
{
    return ASN_OCTET_STR;
}

/** @class Notification
 *  @brief Notification interface.
 *
 *  This class implements the sendTrap function which
 *  send the list of objects defined by the specific notification
 *  to the configured SNMP manager.
 */

class Notification
{

  public:
    Notification() = default;
    Notification(const Notification&) = delete;
    Notification(Notification&&) = default;
    Notification& operator=(const Notification&) = delete;
    Notification& operator=(Notification&&) = default;
    virtual ~Notification() = default;

    /** @brief Send the snmp trap to the configured
     *          manager.
     */
    void sendTrap();

  protected:
    /** @brief Add the variable in the snmp pdu object.
     *  @param[in] pdu - SNMP pdu object.
     *  @param[in] objID -  SNMP object identifier.
     *  @param[in] objIDLen - Object identifier length.
     *  @param[in] type - ASN type of object.
     *  @param[in] val - Value of the object.
     *  @returns true on success otherwise false.
     */
    bool addPDUVar(netsnmp_pdu& pdu, const OID& objID, size_t objIDLen,
                   u_char type, Value val);

    /** @brief get the SNMP notification type in the mib
     *         defined format.
     *         This is pure virtual function all the subclasses
     *         need to provide its own defined type.
     *  @returns the notification type string.
     */
    virtual std::pair<OID, OID_LEN> getTrapOID() = 0;

    /** @brief get all the objects meta data defined under
     *         this notification.
     */
    virtual std::vector<Object> getFieldOIDList() = 0;
};

class TestErrorNotification;

/** @class ErrorNotification
 *  @brief subclass of Notification
 *
 *  A Error Notification represents the objects needed by the
 *  Error Object.
 */
class OBMCErrorNotification : public Notification
{

  private:
    uint32_t OBMCErrorID;
    uint64_t OBMCErrorTimestamp;
    int32_t OBMCErrorSeverity;
    std::string OBMCErrorMessage;

  public:
    OBMCErrorNotification() = default;
    OBMCErrorNotification(const OBMCErrorNotification&) = delete;
    OBMCErrorNotification(OBMCErrorNotification&&) = default;
    OBMCErrorNotification& operator=(const OBMCErrorNotification&) = delete;
    OBMCErrorNotification& operator=(OBMCErrorNotification&&) = default;
    ~OBMCErrorNotification() = default;

    /** @brief Constructor
     *  @param[in] id - The error entry id.
     *  @param[in] ts - The commit timestamp.
     *  @param[in] sev - The severity of the error.
     *  @param[in] msg - The message of the error.
     */
    OBMCErrorNotification(uint32_t id, uint64_t ts, int32_t sev,
                          std::string msg) :
        OBMCErrorID(id),
        OBMCErrorTimestamp(ts), OBMCErrorSeverity(sev), OBMCErrorMessage(msg)
    {}

  protected:
    std::pair<OID, OID_LEN> getTrapOID() override
    {
        // notification sub types
        OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 0, 1};
        OID_LEN idLen = 11;
        return std::make_pair<OID, OID_LEN>(std::move(id), std::move(idLen));
    }

    std::vector<Object> getFieldOIDList() override
    {
        std::vector<Object> objectList;

        OID_LEN idLen = 11;
        OID id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 1};
        auto type = getASNType<decltype(OBMCErrorID)>();
        auto tuple =
            std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type, OBMCErrorID);

        objectList.emplace_back(std::move(tuple));

        id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 2};
        type = getASNType<decltype(OBMCErrorTimestamp)>();
        tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
                                                      OBMCErrorTimestamp);

        objectList.emplace_back(std::move(tuple));

        id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 3};
        type = getASNType<decltype(OBMCErrorSeverity)>();

        tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
                                                      OBMCErrorSeverity);

        objectList.emplace_back(std::move(tuple));

        id = {1, 3, 6, 1, 4, 1, 49871, 1, 0, 1, 4};
        type = getASNType<decltype(OBMCErrorMessage)>();

        tuple = std::tuple<OID, OID_LEN, Type, Value>(id, idLen, type,
                                                      OBMCErrorMessage);

        objectList.emplace_back(std::move(tuple));

        return objectList;
    }

    friend class TestErrorNotification;
};

} // namespace snmp
} // namespace network
} // namespace phosphor
