#include <algorithm>
#include <array>
#include <ipmid/api.hpp>
#include <ipmid/registration.hpp>
#include <ipmid/utils.hpp>
#include <ipmiwhitelist.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <settings.hpp>
#include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp>

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;

namespace ipmi
{

// put the filter provider in an unnamed namespace
namespace
{

/** @class WhitelistFilter
 *
 * Class that implements an IPMI message filter based
 * on incoming interface and a restriction mode setting
 */
class WhitelistFilter
{
  public:
    WhitelistFilter();
    ~WhitelistFilter() = default;
    WhitelistFilter(WhitelistFilter const&) = delete;
    WhitelistFilter(WhitelistFilter&&) = delete;
    WhitelistFilter& operator=(WhitelistFilter const&) = delete;
    WhitelistFilter& operator=(WhitelistFilter&&) = delete;

  private:
    void postInit();
    void cacheRestrictedMode();
    void handleRestrictedModeChange(sdbusplus::message::message& m);
    ipmi::Cc filterMessage(ipmi::message::Request::ptr request);

    bool restrictedMode = true;
    std::shared_ptr<sdbusplus::asio::connection> bus;
    std::unique_ptr<settings::Objects> objects;
    std::unique_ptr<sdbusplus::bus::match::match> modeChangeMatch;

    static constexpr const char restrictionModeIntf[] =
        "xyz.openbmc_project.Control.Security.RestrictionMode";
};

WhitelistFilter::WhitelistFilter()
{
    bus = getSdBus();

    log<level::INFO>("Loading whitelist filter");

    ipmi::registerFilter(ipmi::prioOpenBmcBase,
                         [this](ipmi::message::Request::ptr request) {
                             return filterMessage(request);
                         });

    // wait until io->run is going to fetch RestrictionMode
    post_work([this]() { postInit(); });
}

void WhitelistFilter::cacheRestrictedMode()
{
    using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
    std::string restrictionModeSetting;
    std::string restrictionModeService;
    try
    {
        restrictionModeSetting = objects->map.at(restrictionModeIntf).at(0);
        restrictionModeService =
            objects->service(restrictionModeSetting, restrictionModeIntf);
    }
    catch (const std::out_of_range& e)
    {
        log<level::ERR>(
            "Could not look up restriction mode interface from cache");
        return;
    }
    bus->async_method_call(
        [this](boost::system::error_code ec, ipmi::Value v) {
            if (ec)
            {
                log<level::ERR>("Error in RestrictionMode Get");
                // Fail-safe to true.
                restrictedMode = true;
                return;
            }
            auto mode = std::get<std::string>(v);
            auto restrictionMode =
                RestrictionMode::convertModesFromString(mode);
            restrictedMode =
                (restrictionMode == RestrictionMode::Modes::Whitelist);
            log<level::INFO>((restrictedMode ? "Set restrictedMode = true"
                                             : "Set restrictedMode = false"));
        },
        restrictionModeService, restrictionModeSetting,
        "org.freedesktop.DBus.Properties", "Get", restrictionModeIntf,
        "RestrictionMode");
}

void WhitelistFilter::handleRestrictedModeChange(sdbusplus::message::message& m)
{
    using namespace sdbusplus::xyz::openbmc_project::Control::Security::server;
    std::string mode;
    m.read(mode);
    RestrictionMode::Modes restrictionMode =
        RestrictionMode::convertModesFromString(mode);
    restrictedMode = (restrictionMode == RestrictionMode::Modes::Whitelist);
    log<level::INFO>((restrictedMode ? "Updated restrictedMode = true"
                                     : "Updated restrictedMode = false"));
}

void WhitelistFilter::postInit()
{
    objects = std::make_unique<settings::Objects>(
        *bus, std::vector<settings::Interface>({restrictionModeIntf}));
    if (!objects)
    {
        log<level::ERR>(
            "Failed to create settings object; defaulting to restricted mode");
        return;
    }

    // Initialize restricted mode
    cacheRestrictedMode();
    // Wait for changes on Restricted mode
    std::string filterStr;
    try
    {
        filterStr = sdbusplus::bus::match::rules::propertiesChanged(
            objects->map.at(restrictionModeIntf).at(0), restrictionModeIntf);
    }
    catch (const std::out_of_range& e)
    {
        log<level::ERR>("Failed to determine restriction mode filter string");
        return;
    }
    modeChangeMatch = std::make_unique<sdbusplus::bus::match::match>(
        *bus, filterStr, [this](sdbusplus::message::message& m) {
            handleRestrictedModeChange(m);
        });
}

ipmi::Cc WhitelistFilter::filterMessage(ipmi::message::Request::ptr request)
{
    if (request->ctx->channel == ipmi::channelSystemIface && restrictedMode)
    {
        if (!std::binary_search(
                whitelist.cbegin(), whitelist.cend(),
                std::make_pair(request->ctx->netFn, request->ctx->cmd)))
        {
            log<level::ERR>("Net function not whitelisted",
                            entry("NETFN=0x%X", int(request->ctx->netFn)),
                            entry("CMD=0x%X", int(request->ctx->cmd)));
            return ipmi::ccInsufficientPrivilege;
        }
    }
    return ipmi::ccSuccess;
}

// instantiate the WhitelistFilter when this shared object is loaded
WhitelistFilter whitelistFilter;

} // namespace

} // namespace ipmi
