/*
// Copyright (c) 2018 Intel 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.
*/

#include "oemcommands.hpp"

#include <boost/algorithm/string.hpp>
#include <ipmid/api.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/log.hpp>

#include <variant>

namespace ipmi
{
void register_netfn_bmc_control_functions() __attribute__((constructor));

static constexpr uint8_t rmcpServiceBitPos = 3;
static constexpr uint8_t webServiceBitPos = 5;
static constexpr uint8_t solServiceBitPos = 6;
static constexpr uint8_t kvmServiceBitPos = 15;

static const std::unordered_map<uint8_t, std::string> bmcServices = {
    // {bit position for service, service object path}
    {rmcpServiceBitPos,
     "/xyz/openbmc_project/control/service/phosphor_2dipmi_2dnet"},
    {webServiceBitPos, "/xyz/openbmc_project/control/service/bmcweb"},
    {solServiceBitPos,
     "/xyz/openbmc_project/control/service/obmc_2dconsole_2dssh"},
    {kvmServiceBitPos, "/xyz/openbmc_project/control/service/start_2dipkvm"},
};

static constexpr uint16_t maskBit15 = 0x8000;

static constexpr const char* objectManagerIntf =
    "org.freedesktop.DBus.ObjectManager";
static constexpr const char* dBusPropIntf = "org.freedesktop.DBus.Properties";
static constexpr const char* serviceConfigBasePath =
    "/xyz/openbmc_project/control/service";
static constexpr const char* serviceConfigAttrIntf =
    "xyz.openbmc_project.Control.Service.Attributes";
static constexpr const char* getMgdObjMethod = "GetManagedObjects";
static constexpr const char* propMasked = "Masked";

std::string getServiceConfigMgrName()
{
    static std::string serviceCfgMgr{};
    if (serviceCfgMgr.empty())
    {
        try
        {
            auto sdbusp = getSdBus();
            serviceCfgMgr = ipmi::getService(*sdbusp, objectManagerIntf,
                                             serviceConfigBasePath);
        }
        catch (const sdbusplus::exception::exception& e)
        {
            serviceCfgMgr.clear();
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error: In fetching disabling service manager name");
            return serviceCfgMgr;
        }
    }
    return serviceCfgMgr;
}

static inline void checkAndThrowError(boost::system::error_code& ec,
                                      const std::string& msg)
{
    if (ec)
    {
        std::string msgToLog = ec.message() + (msg.empty() ? "" : " - " + msg);
        phosphor::logging::log<phosphor::logging::level::ERR>(msgToLog.c_str());
        throw sdbusplus::exception::SdBusError(-EIO, msgToLog.c_str());
    }
    return;
}

static inline bool getEnabledValue(const DbusInterfaceMap& intfMap)
{
    for (const auto& intf : intfMap)
    {
        if (intf.first == serviceConfigAttrIntf)
        {
            auto it = intf.second.find(propMasked);
            if (it == intf.second.end())
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Error: in getting Masked property value");
                throw sdbusplus::exception::SdBusError(
                    -EIO, "ERROR in reading Masked property value");
            }
            // return !Masked value
            return !std::get<bool>(it->second);
        }
    }
    return false;
}

ipmi::RspType<> setBmcControlServices(boost::asio::yield_context yield,
                                      uint8_t state, uint16_t serviceValue)
{
    constexpr uint16_t servicesRsvdMask = 0x3F97;
    constexpr uint8_t enableService = 0x1;

    if ((state > enableService) || (serviceValue & servicesRsvdMask) ||
        !serviceValue)
    {
        return ipmi::responseInvalidFieldRequest();
    }
    try
    {
        auto sdbusp = getSdBus();
        boost::system::error_code ec;
        auto objectMap = sdbusp->yield_method_call<ObjectValueTree>(
            yield, ec, getServiceConfigMgrName().c_str(), serviceConfigBasePath,
            objectManagerIntf, getMgdObjMethod);
        checkAndThrowError(ec, "GetMangagedObjects for service cfg failed");

        for (const auto& services : bmcServices)
        {
            // services.first holds the bit position of the service, check
            // whether it has to be updated.
            const uint16_t serviceMask = 1 << services.first;
            if (!(serviceValue & serviceMask))
            {
                continue;
            }
            for (const auto& obj : objectMap)
            {
                if (boost::algorithm::starts_with(obj.first.str,
                                                  services.second))
                {
                    if (state != getEnabledValue(obj.second))
                    {
                        ec.clear();
                        sdbusp->yield_method_call<>(
                            yield, ec, getServiceConfigMgrName().c_str(),
                            obj.first.str, dBusPropIntf, "Set",
                            serviceConfigAttrIntf, propMasked,
                            std::variant<bool>(!state));
                        checkAndThrowError(ec, "Set Masked property failed");
                        // Multiple instances may be present, so continue
                    }
                }
            }
        }
    }
    catch (const sdbusplus::exception::exception& e)
    {
        return ipmi::responseUnspecifiedError();
    }
    return ipmi::responseSuccess();
}

ipmi::RspType<uint16_t> getBmcControlServices(boost::asio::yield_context yield)
{
    uint16_t serviceValue = 0;
    try
    {
        auto sdbusp = getSdBus();
        boost::system::error_code ec;
        auto objectMap = sdbusp->yield_method_call<ObjectValueTree>(
            yield, ec, getServiceConfigMgrName().c_str(), serviceConfigBasePath,
            objectManagerIntf, getMgdObjMethod);
        checkAndThrowError(ec, "GetMangagedObjects for service cfg failed");

        for (const auto& services : bmcServices)
        {
            for (const auto& obj : objectMap)
            {
                if (boost::algorithm::starts_with(obj.first.str,
                                                  services.second))
                {
                    serviceValue |= getEnabledValue(obj.second)
                                    << services.first;
                    break;
                }
            }
        }
    }
    catch (const sdbusplus::exception::exception& e)
    {
        return ipmi::responseUnspecifiedError();
    }
    // Bit 14 should match bit 15 as single service maintains Video & USB
    // redirection
    serviceValue |= (serviceValue & maskBit15) >> 1;
    return ipmi::responseSuccess(serviceValue);
}

void register_netfn_bmc_control_functions()
{
    registerHandler(prioOpenBmcBase, intel::netFnGeneral,
                    intel::general::cmdControlBmcServices, Privilege::Admin,
                    setBmcControlServices);

    registerHandler(prioOpenBmcBase, intel::netFnGeneral,
                    intel::general::cmdGetBmcServiceStatus, Privilege::User,
                    getBmcControlServices);
}
} // namespace ipmi
