#include "config.h"

#include "occ_pass_through.hpp"

#include "elog-errors.hpp"

#include <errno.h>
#include <fcntl.h>
#include <fmt/core.h>
#include <unistd.h>

#include <org/open_power/OCC/Device/error.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/log.hpp>

#include <algorithm>
#include <memory>
#include <string>

namespace open_power
{
namespace occ
{

using namespace phosphor::logging;
using namespace sdbusplus::org::open_power::OCC::Device::Error;

PassThrough::PassThrough(
    const char* path
#ifdef POWER10
    ,
    std::unique_ptr<open_power::occ::powermode::PowerMode>& powerModeRef
#endif
    ) :
    Iface(utils::getBus(), path),
    path(path),
#ifdef POWER10
    pmode(powerModeRef),
#endif
    devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)),
    occInstance(this->path.back() - '0'),
    activeStatusSignal(
        utils::getBus(),
        sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"),
        std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this,
                  std::placeholders::_1)),
    occCmd(occInstance, path)
{
    // Nothing to do.
}

std::vector<int32_t> PassThrough::send(std::vector<int32_t> command)
{
    std::vector<int32_t> response{};

    // OCC only understands [bytes] so need array of bytes. Doing this
    // because rest-server currently treats all int* as 32 bit integer.
    std::vector<uint8_t> cmdInBytes, rsp;
    cmdInBytes.resize(command.size());

    // Populate uint8_t version of vector.
    std::transform(command.begin(), command.end(), cmdInBytes.begin(),
                   [](decltype(cmdInBytes)::value_type x) { return x; });

    rsp = send(cmdInBytes);

    response.resize(rsp.size());
    std::transform(rsp.begin(), rsp.end(), response.begin(),
                   [](decltype(response)::value_type x) { return x; });

    return response;
}

std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command)
{
    std::vector<uint8_t> response{};

    log<level::DEBUG>(
        fmt::format("PassThrough::send() Sending 0x{:02X} command to OCC{}",
                    command.front(), occInstance)
            .c_str());
    CmdStatus status = occCmd.send(command, response);
    if (status == CmdStatus::SUCCESS)
    {
        if (response.size() >= 5)
        {
            log<level::DEBUG>(
                fmt::format("PassThrough::send() response had {} bytes",
                            response.size())
                    .c_str());
        }
        else
        {
            log<level::ERR>("PassThrough::send() Invalid OCC response");
            dump_hex(response);
        }
    }
    else
    {
        if (status == CmdStatus::OPEN_FAILURE)
        {
            log<level::WARNING>("PassThrough::send() - OCC not active yet");
        }
        else
        {
            log<level::ERR>("PassThrough::send() - OCC command failed!");
        }
    }

    return response;
}

bool PassThrough::setMode(const uint8_t mode, const uint16_t modeData)
{
#ifdef POWER10
    SysPwrMode newMode = SysPwrMode(mode);

    if ((!VALID_POWER_MODE_SETTING(newMode)) &&
        (!VALID_OEM_POWER_MODE_SETTING(newMode)))
    {
        log<level::ERR>(
            fmt::format(
                "PassThrough::setMode() Unsupported mode {} requested (0x{:04X})",
                newMode, modeData)
                .c_str());
        return false;
    }

    if (((newMode == SysPwrMode::FFO) || (newMode == SysPwrMode::SFP)) &&
        (modeData == 0))
    {
        log<level::ERR>(
            fmt::format(
                "PassThrough::setMode() Mode {} requires non-zero frequency point.",
                newMode)
                .c_str());
        return false;
    }

    log<level::INFO>(
        fmt::format("PassThrough::setMode() Setting Power Mode {} (data: {})",
                    newMode, modeData)
            .c_str());
    return pmode->setMode(newMode, modeData);
#else
    log<level::DEBUG>(
        fmt::format(
            "PassThrough::setMode() No support to setting Power Mode {} (data: {})",
            mode, modeData)
            .c_str());
    return false;
#endif
}

// Called at OCC Status change signal
void PassThrough::activeStatusEvent(sdbusplus::message::message& msg)
{
    std::string statusInterface;
    std::map<std::string, std::variant<bool>> msgData;
    msg.read(statusInterface, msgData);

    auto propertyMap = msgData.find("OccActive");
    if (propertyMap != msgData.end())
    {
        // Extract the OccActive property
        if (std::get<bool>(propertyMap->second))
        {
            occActive = true;
        }
        else
        {
            occActive = false;
        }
    }
    return;
}

} // namespace occ
} // namespace open_power
