/*
// 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 <types.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 constexpr std::array<std::pair<uint8_t, const char*>, 4> bmcServices = {{
    // {bit position for service, service name}
    {rmcpServiceBitPos, "phosphor-ipmi-net"},
    {webServiceBitPos, "bmcweb"},
    {solServiceBitPos, "obmc-console-ssh"},
    {kvmServiceBitPos, "obmc-ikvm"},
}};

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_t& 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.filename(),
                                                  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,
                            ipmi::DbusVariant(!state));
                        checkAndThrowError(ec, "Set Masked property failed");
                        // Multiple instances may be present, so continue
                    }
                }
            }
        }
    }
    catch (const sdbusplus::exception_t& 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.filename(),
                                                  services.second))
                {
                    serviceValue |= getEnabledValue(obj.second)
                                    << services.first;
                    break;
                }
            }
        }
    }
    catch (const sdbusplus::exception_t& 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
