#include "softoff.hpp"

#include "common/instance_id.hpp"
#include "common/transport.hpp"
#include "common/utils.hpp"

#include <libpldm/entity.h>
#include <libpldm/platform.h>
#include <libpldm/state_set.h>

#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/bus.hpp>
#include <sdeventplus/clock.hpp>
#include <sdeventplus/exception.hpp>
#include <sdeventplus/source/io.hpp>
#include <sdeventplus/source/time.hpp>
#include <xyz/openbmc_project/State/Host/common.hpp>

#include <array>
#include <filesystem>
#include <fstream>

PHOSPHOR_LOG2_USING;

using HostState = sdbusplus::common::xyz::openbmc_project::state::Host;

namespace pldm
{
using namespace sdeventplus;
using namespace sdeventplus::source;
namespace fs = std::filesystem;
constexpr auto clockId = sdeventplus::ClockId::RealTime;
using Clock = Clock<clockId>;
using Timer = Time<clockId>;

using sdbusplus::exception::SdBusError;

// Shutdown effecter terminus ID, set when we look up the effecter
pldm::pdr::TerminusID TID = 0;

namespace sdbusRule = sdbusplus::bus::match::rules;

SoftPowerOff::SoftPowerOff(sdbusplus::bus_t& bus, sd_event* event,
                           pldm::InstanceIdDb& instanceIdDb) :
    timer(event), instanceIdDb(instanceIdDb)
{
    auto jsonData = parseConfig();

    if (jsonData.is_discarded())
    {
        error("Failed to parse softoff config JSON file");
        return;
    }

    getHostState();
    if (hasError || completed)
    {
        return;
    }
    const std::vector<Json> emptyJsonList{};
    auto entries = jsonData.value("entries", emptyJsonList);
    for (const auto& entry : entries)
    {
        TID = entry.value("tid", 0);
        pldm::pdr::EntityType entityType = entry.value("entityType", 0);
        pldm::pdr::StateSetId stateSetId = entry.value("stateSetId", 0);

        bool effecterFound = getEffecterID(entityType, stateSetId);
        if (effecterFound)
        {
            auto rc = getSensorInfo(entityType, stateSetId);
            if (rc != PLDM_SUCCESS)
            {
                error("Failed to get Sensor PDRs, response code '{RC}'", "RC",
                      lg2::hex, rc);
                hasError = true;
                return;
            }
            break;
        }
        else
        {
            continue;
        }
    }

    // Matches on the pldm StateSensorEvent signal
    pldmEventSignal = std::make_unique<sdbusplus::bus::match_t>(
        bus,
        sdbusRule::type::signal() + sdbusRule::member("StateSensorEvent") +
            sdbusRule::path("/xyz/openbmc_project/pldm") +
            sdbusRule::interface("xyz.openbmc_project.PLDM.Event"),
        std::bind(std::mem_fn(&SoftPowerOff::hostSoftOffComplete), this,
                  std::placeholders::_1));
}

int SoftPowerOff::getHostState()
{
    try
    {
        pldm::utils::PropertyValue propertyValue =
            pldm::utils::DBusHandler().getDbusPropertyVariant(
                "/xyz/openbmc_project/state/host0",
                HostState::property_names::current_host_state,
                HostState::interface);

        if ((std::get<std::string>(propertyValue) !=
             "xyz.openbmc_project.State.Host.HostState.Running") &&
            (std::get<std::string>(propertyValue) !=
             "xyz.openbmc_project.State.Host.HostState.TransitioningToOff"))
        {
            // Host state is not "Running", this app should return success
            completed = true;
            return PLDM_SUCCESS;
        }
    }
    catch (const std::exception& e)
    {
        error(
            "PLDM remote terminus soft off. Can't get current remote terminus state, error - {ERROR}",
            "ERROR", e);
        hasError = true;
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

void SoftPowerOff::hostSoftOffComplete(sdbusplus::message_t& msg)
{
    pldm::pdr::TerminusID msgTID;
    pldm::pdr::SensorID msgSensorID;
    pldm::pdr::SensorOffset msgSensorOffset;
    pldm::pdr::EventState msgEventState;
    pldm::pdr::EventState msgPreviousEventState;

    // Read the msg and populate each variable
    msg.read(msgTID, msgSensorID, msgSensorOffset, msgEventState,
             msgPreviousEventState);

    if (msgSensorID == sensorID && msgSensorOffset == sensorOffset &&
        msgEventState == PLDM_SW_TERM_GRACEFUL_SHUTDOWN && msgTID == TID)
    {
        // Receive Graceful shutdown completion event message. Disable the timer
        auto rc = timer.stop();
        if (rc < 0)
        {
            error(
                "Failure to STOP the timer of PLDM soft off, response code '{RC}'",
                "RC", rc);
        }

        // This marks the completion of pldm soft power off.
        completed = true;
    }
}

Json SoftPowerOff::parseConfig()
{
    fs::path softoffConfigJson(
        fs::path(SOFTOFF_CONFIG_JSON) / "softoff_config.json");

    if (!fs::exists(softoffConfigJson) || fs::is_empty(softoffConfigJson))
    {
        error(
            "Failed to parse softoff config JSON file '{PATH}', file does not exist",
            "PATH", softoffConfigJson);
        return PLDM_ERROR;
    }

    std::ifstream jsonFile(softoffConfigJson);
    return Json::parse(jsonFile);
}

bool SoftPowerOff::getEffecterID(pldm::pdr::EntityType& entityType,
                                 pldm::pdr::StateSetId& stateSetId)
{
    auto& bus = pldm::utils::DBusHandler::getBus();
    try
    {
        std::vector<std::vector<uint8_t>> response{};
        auto method = bus.new_method_call(
            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
            "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
        method.append(TID, entityType, stateSetId);
        auto responseMsg = bus.call(method, dbusTimeout);

        responseMsg.read(response);
        if (response.size())
        {
            for (auto& rep : response)
            {
                auto softoffPdr = new (rep.data()) pldm_state_effecter_pdr;
                effecterID = softoffPdr->effecter_id;
            }
        }
        else
        {
            return false;
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error("Failed to get softPowerOff PDR, error - {ERROR}", "ERROR", e);
        return false;
    }
    return true;
}

int SoftPowerOff::getSensorInfo(pldm::pdr::EntityType& entityType,
                                pldm::pdr::StateSetId& stateSetId)
{
    try
    {
        auto& bus = pldm::utils::DBusHandler::getBus();
        std::vector<std::vector<uint8_t>> Response{};
        auto method = bus.new_method_call(
            "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
            "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
        method.append(TID, entityType, stateSetId);

        auto ResponseMsg = bus.call(method, dbusTimeout);

        ResponseMsg.read(Response);

        if (Response.size() == 0)
        {
            error("No sensor PDR has been found that matches the criteria");
            return PLDM_ERROR;
        }

        pldm_state_sensor_pdr* pdr = nullptr;
        for (auto& rep : Response)
        {
            pdr = new (rep.data()) pldm_state_sensor_pdr;
            if (!pdr)
            {
                error("Failed to get state sensor PDR.");
                return PLDM_ERROR;
            }
        }

        sensorID = pdr->sensor_id;

        auto compositeSensorCount = pdr->composite_sensor_count;
        auto possibleStatesStart = pdr->possible_states;

        for (auto offset = 0; offset < compositeSensorCount; offset++)
        {
            auto possibleStates = new (possibleStatesStart)
                state_sensor_possible_states;
            auto setId = possibleStates->state_set_id;
            auto possibleStateSize = possibleStates->possible_states_size;

            if (setId == PLDM_STATE_SET_SW_TERMINATION_STATUS)
            {
                sensorOffset = offset;
                break;
            }
            possibleStatesStart +=
                possibleStateSize + sizeof(setId) + sizeof(possibleStateSize);
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error("Failed to get state sensor PDR during soft-off, error - {ERROR}",
              "ERROR", e);
        return PLDM_ERROR;
    }

    return PLDM_SUCCESS;
}

int SoftPowerOff::hostSoftOff(sdeventplus::Event& event)
{
    constexpr uint8_t effecterCount = 1;
    PldmTransport pldmTransport{};
    uint8_t mctpEID;

    mctpEID = pldm::utils::readHostEID();
    // TODO: fix mapping to work around OpenBMC ecosystem deficiencies
    pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEID);

    uint8_t effecterState;
    auto requestHostTransition =
        pldm::utils::DBusHandler().getDbusProperty<std::string>(
            "/xyz/openbmc_project/state/host0",
            HostState::property_names::requested_host_transition,
            sdbusplus::common::xyz::openbmc_project::state::Host::interface);
    if (requestHostTransition !=
        "xyz.openbmc_project.State.Host.Transition.Off")
    {
        effecterState = PLDM_SW_TERM_GRACEFUL_RESTART_REQUESTED;
    }
    else
    {
        effecterState = PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED;
    }

    std::array<uint8_t,
               sizeof(pldm_msg_hdr) + sizeof(effecterID) +
                   sizeof(effecterCount) + sizeof(set_effecter_state_field)>
        requestMsg{};
    auto request = new (requestMsg.data()) pldm_msg;
    set_effecter_state_field stateField{PLDM_REQUEST_SET, effecterState};
    auto instanceIdResult = instanceIdDb.next(pldmTID);
    if (!instanceIdResult)
    {
        return PLDM_ERROR;
    }
    auto instanceID = instanceIdResult.value();
    auto rc = encode_set_state_effecter_states_req(
        instanceID, effecterID, effecterCount, &stateField, request);
    if (rc != PLDM_SUCCESS)
    {
        instanceIdDb.free(pldmTID, instanceID);
        error(
            "Failed to encode set state effecter states request message, response code '{RC}'",
            "RC", lg2::hex, rc);
        return PLDM_ERROR;
    }

    // Add a timer to the event loop, default 30s.
    auto timerCallback = [=, this](Timer& /*source*/,
                                   Timer::TimePoint /*time*/) mutable {
        if (!responseReceived)
        {
            instanceIdDb.free(pldmTID, instanceID);
            error(
                "PLDM soft off failed, can't get the response for the PLDM request msg. Time out! Exit the pldm-softpoweroff");
            exit(-1);
        }
        return;
    };
    Timer time(event, (Clock(event).now() + std::chrono::seconds{30}),
               std::chrono::seconds{1}, std::move(timerCallback));

    // Add a callback to handle EPOLLIN on fd
    auto callback = [=, &pldmTransport,
                     this](IO& io, int fd, uint32_t revents) mutable {
        if (fd != pldmTransport.getEventSource())
        {
            return;
        }

        if (!(revents & EPOLLIN))
        {
            return;
        }

        void* responseMsg = nullptr;
        size_t responseMsgSize{};
        pldm_tid_t srcTID = pldmTID;

        auto rc = pldmTransport.recvMsg(pldmTID, responseMsg, responseMsgSize);
        if (rc)
        {
            error(
                "Failed to receive pldm data during soft-off, response code '{RC}'",
                "RC", rc);
            return;
        }

        std::unique_ptr<void, decltype(std::free)*> responseMsgPtr{
            responseMsg, std::free};

        // We've got the response meant for the PLDM request msg that was
        // sent out
        io.set_enabled(Enabled::Off);
        auto response = new (responseMsgPtr.get()) pldm_msg;

        if (srcTID != pldmTID ||
            !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
        {
            /* This isn't the response we were looking for */
            return;
        }

        /* We have the right response, release the instance ID and process */
        io.set_enabled(Enabled::Off);
        instanceIdDb.free(pldmTID, instanceID);

        if (response->payload[0] != PLDM_SUCCESS)
        {
            error("Getting the wrong response, response code '{RC}'", "RC",
                  response->payload[0]);
            exit(-1);
        }

        responseReceived = true;

        // Start Timer
        using namespace std::chrono;
        auto timeMicroseconds =
            duration_cast<microseconds>(seconds(SOFTOFF_TIMEOUT_SECONDS));

        auto ret = startTimer(timeMicroseconds);
        if (ret < 0)
        {
            error(
                "Failure to start remote terminus soft off wait timer, Exit the pldm-softpoweroff with response code:{NUM}",
                "NUM", ret);
            exit(-1);
        }
        else
        {
            error(
                "Timer started waiting for remote terminus soft off, timeout in sec '{TIMEOUT_SEC}'",
                "TIMEOUT_SEC", SOFTOFF_TIMEOUT_SECONDS);
        }
        return;
    };
    IO io(event, pldmTransport.getEventSource(), EPOLLIN, std::move(callback));

    // Asynchronously send the PLDM request
    rc = pldmTransport.sendMsg(pldmTID, requestMsg.data(), requestMsg.size());
    if (0 > rc)
    {
        instanceIdDb.free(pldmTID, instanceID);
        error(
            "Failed to send message/receive response, response code '{RC}' and error - {ERROR}",
            "RC", rc, "ERROR", errno);
        return PLDM_ERROR;
    }

    // Time out or soft off complete
    while (!isCompleted() && !isTimerExpired())
    {
        try
        {
            event.run(std::nullopt);
        }
        catch (const sdeventplus::SdEventError& e)
        {
            instanceIdDb.free(pldmTID, instanceID);
            error(
                "Failed to process request while remote terminus soft off, error - {ERROR}",
                "ERROR", e);
            return PLDM_ERROR;
        }
    }

    return PLDM_SUCCESS;
}

int SoftPowerOff::startTimer(const std::chrono::microseconds& usec)
{
    return timer.start(usec);
}
} // namespace pldm
