#include "watchdog.hpp"

#include <cstdint>
#include <endian.h>
#include <phosphor-logging/log.hpp>
#include <string>

#include "watchdog_service.hpp"
#include "host-ipmid/ipmid-api.h"
#include "ipmid.hpp"

using phosphor::logging::level;
using phosphor::logging::log;

ipmi_ret_t ipmi_app_watchdog_reset(
        ipmi_netfn_t netfn,
        ipmi_cmd_t cmd,
        ipmi_request_t request,
        ipmi_response_t response,
        ipmi_data_len_t data_len,
        ipmi_context_t context)
{
    // We never return data with this command so immediately get rid of it
    *data_len = 0;

    try
    {
        WatchdogService wd_service;
        WatchdogService::Properties wd_prop = wd_service.getProperties();

        // Notify the caller if we haven't initialized our timer yet
        // so it can configure actions and timeouts
        if (!wd_prop.initialized)
        {
            return IPMI_WDOG_CC_NOT_INIT;
        }

        // Reset the countdown to make sure we don't expire our timer
        wd_service.setTimeRemaining(wd_prop.interval);

        // The spec states that the timer is activated by reset
        wd_service.setEnabled(true);

        return IPMI_CC_OK;
    }
    catch (const std::exception& e)
    {
        const std::string e_str = std::string("wd_reset: ") + e.what();
        log<level::ERR>(e_str.c_str());
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
    catch (...)
    {
        log<level::ERR>("wd_reset: Unknown Error");
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
}

static constexpr uint8_t wd_dont_stop = 0x1 << 6;
static constexpr uint8_t wd_timeout_action_mask = 0x3;

enum class IpmiAction : uint8_t {
    None = 0x0,
    HardReset = 0x1,
    PowerOff = 0x2,
    PowerCycle = 0x3,
};

/** @brief Converts an IPMI Watchdog Action to DBUS defined action
 *  @param[in] ipmi_action The IPMI Watchdog Action
 *  @return The Watchdog Action that the ipmi_action maps to
 */
WatchdogService::Action ipmiActionToWdAction(IpmiAction ipmi_action)
{
    switch(ipmi_action)
    {
        case IpmiAction::None:
        {
            return WatchdogService::Action::None;
        }
        case IpmiAction::HardReset:
        {
            return WatchdogService::Action::HardReset;
        }
        case IpmiAction::PowerOff:
        {
            return WatchdogService::Action::PowerOff;
        }
        case IpmiAction::PowerCycle:
        {
            return WatchdogService::Action::PowerCycle;
        }
        default:
        {
            throw std::domain_error("IPMI Action is invalid");
        }
    }
}

struct wd_set_req {
    uint8_t timer_use;
    uint8_t timer_action;
    uint8_t pretimeout;  // (seconds)
    uint8_t expire_flags;
    uint16_t initial_countdown;  // Little Endian (deciseconds)
}  __attribute__ ((packed));
static_assert(sizeof(wd_set_req) == 6, "wd_set_req has invalid size.");
static_assert(sizeof(wd_set_req) <= MAX_IPMI_BUFFER,
        "wd_get_res can't fit in request buffer.");

ipmi_ret_t ipmi_app_watchdog_set(
        ipmi_netfn_t netfn,
        ipmi_cmd_t cmd,
        ipmi_request_t request,
        ipmi_response_t response,
        ipmi_data_len_t data_len,
        ipmi_context_t context)
{
    // Extract the request data
    if (*data_len < sizeof(wd_set_req))
    {
        *data_len = 0;
        return IPMI_CC_REQ_DATA_LEN_INVALID;
    }
    wd_set_req req;
    memcpy(&req, request, sizeof(req));
    req.initial_countdown = le16toh(req.initial_countdown);
    *data_len = 0;

    try
    {
        WatchdogService wd_service;
        // Stop the timer if the don't stop bit is not set
        if (!(req.timer_use & wd_dont_stop))
        {
            wd_service.setEnabled(false);
        }

        // Set the action based on the request
        const auto ipmi_action = static_cast<IpmiAction>(
                req.timer_action & wd_timeout_action_mask);
        wd_service.setExpireAction(ipmiActionToWdAction(ipmi_action));

        // Set the new interval and the time remaining deci -> mill seconds
        const uint64_t interval = req.initial_countdown * 100;
        wd_service.setInterval(interval);
        wd_service.setTimeRemaining(interval);

        // Mark as initialized so that future resets behave correctly
        wd_service.setInitialized(true);

        return IPMI_CC_OK;
    }
    catch (const std::domain_error &)
    {
        return IPMI_CC_INVALID_FIELD_REQUEST;
    }
    catch (const std::exception& e)
    {
        const std::string e_str = std::string("wd_set: ") + e.what();
        log<level::ERR>(e_str.c_str());
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
    catch (...)
    {
        log<level::ERR>("wd_set: Unknown Error");
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
}

/** @brief Converts a DBUS Watchdog Action to IPMI defined action
 *  @param[in] wd_action The DBUS Watchdog Action
 *  @return The IpmiAction that the wd_action maps to
 */
IpmiAction wdActionToIpmiAction(WatchdogService::Action wd_action)
{
    switch(wd_action)
    {
        case WatchdogService::Action::None:
        {
            return IpmiAction::None;
        }
        case WatchdogService::Action::HardReset:
        {
            return IpmiAction::HardReset;
        }
        case WatchdogService::Action::PowerOff:
        {
            return IpmiAction::PowerOff;
        }
        case WatchdogService::Action::PowerCycle:
        {
            return IpmiAction::PowerCycle;
        }
        default:
        {
            // We have no method via IPMI to signal that the action is unknown
            // or unmappable in some way.
            // Just ignore the error and return NONE so the host can reconcile.
            return IpmiAction::None;
        }
    }
}

struct wd_get_res {
    uint8_t timer_use;
    uint8_t timer_action;
    uint8_t pretimeout;
    uint8_t expire_flags;
    uint16_t initial_countdown;  // Little Endian (deciseconds)
    uint16_t present_countdown;  // Little Endian (deciseconds)
}  __attribute__ ((packed));
static_assert(sizeof(wd_get_res) == 8, "wd_get_res has invalid size.");
static_assert(sizeof(wd_get_res) <= MAX_IPMI_BUFFER,
        "wd_get_res can't fit in response buffer.");

static constexpr uint8_t wd_dont_log = 0x1 << 7;
static constexpr uint8_t wd_running = 0x1 << 6;

ipmi_ret_t ipmi_app_watchdog_get(
        ipmi_netfn_t netfn,
        ipmi_cmd_t cmd,
        ipmi_request_t request,
        ipmi_response_t response,
        ipmi_data_len_t data_len,
        ipmi_context_t context)
{
    // Assume we will fail and send no data outside the return code
    *data_len = 0;

    try
    {
        WatchdogService wd_service;
        WatchdogService::Properties wd_prop = wd_service.getProperties();

        // Build and return the response
        wd_get_res res;
        res.timer_use = wd_dont_log;
        res.timer_action = static_cast<uint8_t>(
                wdActionToIpmiAction(wd_prop.expireAction));
        if (wd_prop.enabled)
        {
            res.timer_use |= wd_running;
        }
        // TODO: Do something about having pretimeout support
        res.pretimeout = 0;
        res.expire_flags = 0;
        // Interval and timeRemaining need converted from milli -> deci seconds
        res.initial_countdown = htole16(wd_prop.interval / 100);
        res.present_countdown = htole16(wd_prop.timeRemaining / 100);

        memcpy(response, &res, sizeof(res));
        *data_len = sizeof(res);
        return IPMI_CC_OK;
    }
    catch (const std::exception& e)
    {
        const std::string e_str = std::string("wd_get: ") + e.what();
        log<level::ERR>(e_str.c_str());
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
    catch (...)
    {
        log<level::ERR>("wd_get: Unknown Error");
        return IPMI_CC_UNSPECIFIED_ERROR;
    }
}
