/*
// Copyright (c) 2019 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 "xyz/openbmc_project/Common/error.hpp"

#include <ipmid/api.hpp>
#include <ipmid/utils.hpp>
#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/timer.hpp>
#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>

#include <fstream>
#include <iostream>
#include <regex>
#include <stdexcept>
#include <string_view>

using namespace phosphor::logging;

namespace ipmi::chassis
{
static constexpr const char* buttonIntf = "xyz.openbmc_project.Chassis.Buttons";

const static constexpr char* idButtonPath =
    "/xyz/openbmc_project/chassis/buttons/id";
static constexpr const char* powerButtonPath =
    "/xyz/openbmc_project/chassis/buttons/power";
static constexpr const char* resetButtonPath =
    "/xyz/openbmc_project/chassis/buttons/reset";
static constexpr const char* interruptButtonPath =
    "/xyz/openbmc_project/chassis/buttons/nmi";

const static constexpr char* idButtonProp = "ButtonPressed";

const static constexpr char* ledService =
    "xyz.openbmc_project.LED.GroupManager";
const static constexpr char* ledIDOnObj =
    "/xyz/openbmc_project/led/groups/enclosure_identify";
const static constexpr char* ledIDBlinkObj =
    "/xyz/openbmc_project/led/groups/enclosure_identify_blink";
const static constexpr char* ledInterface = "xyz.openbmc_project.Led.Group";
const static constexpr char* ledProp = "Asserted";
enum class ChassisIDState
{
    off = 0,
    temporary = 1,
    indefinite = 2,
};
static ChassisIDState chassisIDState = ChassisIDState::off;

constexpr size_t defaultIdentifyTimeOut = 15;

std::unique_ptr<sdbusplus::Timer> identifyTimer
    __attribute__((init_priority(101)));
std::unique_ptr<sdbusplus::bus::match_t> matchPtr
    __attribute__((init_priority(101)));

static void registerChassisFunctions() __attribute__((constructor));

static ipmi::ServiceCache LEDService(ledInterface, ledIDBlinkObj);

void enclosureIdentifyLed(const char* objName, bool isIdLedOn)
{
    auto bus = getSdBus();

    try
    {
        std::string service = LEDService.getService(*bus);
        setDbusProperty(*bus, service, objName, ledInterface, ledProp,
                        isIdLedOn);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("enclosureIdentifyLed: can't set property",
                        entry("ERR=%s", e.what()));
    }
}

bool getIDState(const char* objName, bool& state)
{
    auto bus = getSdBus();

    try
    {
        std::string service = LEDService.getService(*bus);
        ipmi::Value enabled = getDbusProperty(*bus, service, objName,
                                              ledInterface, ledProp);
        state = std::get<bool>(enabled);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Fail to get property", entry("PATH=%s", objName),
                        entry("ERROR=%s", e.what()));
        return false;
    }
    return true;
}

void enclosureIdentifyLedBlinkOff()
{
    chassisIDState = ChassisIDState::off;
    enclosureIdentifyLed(ledIDBlinkObj, false);
}

void idButtonPropChanged(sdbusplus::message_t& msg)
{
    bool asserted = false;
    bool buttonPressed = false;

    std::map<std::string, ipmi::Value> props;
    std::vector<std::string> inval;
    std::string iface;
    msg.read(iface, props, inval);

    for (const auto& t : props)
    {
        auto key = t.first;
        auto value = t.second;

        if (key == idButtonProp)
        {
            buttonPressed = std::get<bool>(value);
        }
        break;
    }

    if (buttonPressed)
    {
        if (identifyTimer->isRunning())
        {
            log<level::INFO>("ID timer is running");
        }

        // make sure timer is stopped
        identifyTimer->stop();

        if (!getIDState(ledIDBlinkObj, asserted))
        {
            return;
        }

        if (asserted)
        {
            // LED is blinking, turn off the LED
            chassisIDState = ChassisIDState::off;
            enclosureIdentifyLed(ledIDBlinkObj, false);
            enclosureIdentifyLed(ledIDOnObj, false);
        }
        else
        {
            // toggle the IED on/off
            if (!getIDState(ledIDOnObj, asserted))
            {
                return;
            }
            enclosureIdentifyLed(ledIDOnObj, !asserted);
        }
    }
}

void createIdentifyTimer()
{
    if (!identifyTimer)
    {
        identifyTimer =
            std::make_unique<sdbusplus::Timer>(enclosureIdentifyLedBlinkOff);
    }
}

ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
                                    std::optional<uint8_t> force)
{
    uint8_t identifyInterval = interval.value_or(defaultIdentifyTimeOut);
    bool forceIdentify = force.value_or(0) & 0x01;

    enclosureIdentifyLed(ledIDOnObj, false);
    identifyTimer->stop();

    if (identifyInterval || forceIdentify)
    {
        enclosureIdentifyLed(ledIDBlinkObj, true);
        if (forceIdentify)
        {
            chassisIDState = ChassisIDState::indefinite;
            return ipmi::responseSuccess();
        }
        chassisIDState = ChassisIDState::temporary;
        // start the timer
        auto time = std::chrono::duration_cast<std::chrono::microseconds>(
            std::chrono::seconds(identifyInterval));
        identifyTimer->start(time);
    }
    else
    {
        chassisIDState = ChassisIDState::off;
        enclosureIdentifyLed(ledIDBlinkObj, false);
    }
    return ipmi::responseSuccess();
}

namespace power_policy
{
/* helper function for Get Chassis Status Command
 */
std::optional<uint2_t> getPowerRestorePolicy()
{
    constexpr const char* powerRestorePath =
        "/xyz/openbmc_project/control/host0/power_restore_policy";
    constexpr const char* powerRestoreIntf =
        "xyz.openbmc_project.Control.Power.RestorePolicy";
    uint2_t restorePolicy = 0;
    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();

    try
    {
        auto service = ipmi::getService(*busp, powerRestoreIntf,
                                        powerRestorePath);

        ipmi::Value result =
            ipmi::getDbusProperty(*busp, service, powerRestorePath,
                                  powerRestoreIntf, "PowerRestorePolicy");
        auto powerRestore = sdbusplus::xyz::openbmc_project::Control::Power::
            server::RestorePolicy::convertPolicyFromString(
                std::get<std::string>(result));

        using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
        switch (powerRestore)
        {
            case RestorePolicy::Policy::AlwaysOff:
                restorePolicy = 0x00;
                break;
            case RestorePolicy::Policy::Restore:
                restorePolicy = 0x01;
                break;
            case RestorePolicy::Policy::AlwaysOn:
                restorePolicy = 0x02;
                break;
            default:
                break;
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("Failed to fetch PowerRestorePolicy property",
                        entry("ERROR=%s", e.what()),
                        entry("PATH=%s", powerRestorePath),
                        entry("INTERFACE=%s", powerRestoreIntf));
        return std::nullopt;
    }
    return std::make_optional(restorePolicy);
}

/*
 * getPowerStatus
 * helper function for Get Chassis Status Command
 * return - optional value for pgood (no value on error)
 */
std::optional<bool> getPowerStatus()
{
    bool powerGood = false;
    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
    try
    {
        constexpr const char* chassisStatePath =
            "/xyz/openbmc_project/state/chassis0";
        constexpr const char* chassisStateIntf =
            "xyz.openbmc_project.State.Chassis";
        auto service = ipmi::getService(*busp, chassisStateIntf,
                                        chassisStatePath);

        ipmi::Value variant =
            ipmi::getDbusProperty(*busp, service, chassisStatePath,
                                  chassisStateIntf, "CurrentPowerState");
        std::string powerState = std::get<std::string>(variant);
        if (powerState == "xyz.openbmc_project.State.Chassis.PowerState.On")
        {
            powerGood = true;
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("Failed to fetch power state property",
                        entry("ERROR=%s", e.what()));
        return std::nullopt;
    }
    return std::make_optional(powerGood);
}

/*
 * getACFailStatus
 * helper function for Get Chassis Status Command
 * return - bool value for ACFail (false on error)
 */
bool getACFailStatus()
{
    constexpr const char* acBootObj =
        "/xyz/openbmc_project/control/host0/ac_boot";
    constexpr const char* acBootIntf = "xyz.openbmc_project.Common.ACBoot";
    std::string acFail;
    std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
    try
    {
        auto service = ipmi::getService(*bus, acBootIntf, acBootObj);

        ipmi::Value variant = ipmi::getDbusProperty(*bus, service, acBootObj,
                                                    acBootIntf, "ACBoot");
        acFail = std::get<std::string>(variant);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            "Failed to fetch ACBoot property", entry("ERROR=%s", e.what()),
            entry("PATH=%s", acBootObj), entry("INTERFACE=%s", acBootIntf));
    }
    return acFail == "True";
}
} // namespace power_policy

static std::optional<bool> getButtonEnabled(const std::string& buttonPath)
{
    bool buttonDisabled = false;
    std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
    try
    {
        auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
        ipmi::Value disabled = ipmi::getDbusProperty(
            *busp, service, buttonPath, buttonIntf, "ButtonMasked");
        buttonDisabled = std::get<bool>(disabled);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>("Fail to get button disabled property",
                        entry("PATH=%s", buttonPath.c_str()),
                        entry("ERROR=%s", e.what()));
        return std::nullopt;
    }
    return std::make_optional(buttonDisabled);
}

static bool setButtonEnabled(const std::string& buttonPath, const bool disabled)
{
    try
    {
        auto service = ipmi::getService(*getSdBus(), buttonIntf, buttonPath);
        ipmi::setDbusProperty(*getSdBus(), service, buttonPath, buttonIntf,
                              "ButtonMasked", disabled);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>("Failed to set button disabled",
                        entry("EXCEPTION=%s, REQUEST=%x", e.what(), disabled));
        return -1;
    }

    return 0;
}

static bool getRestartCause(ipmi::Context::ptr& ctx, std::string& restartCause)
{
    constexpr const char* restartCausePath =
        "/xyz/openbmc_project/control/host0/restart_cause";
    constexpr const char* restartCauseIntf =
        "xyz.openbmc_project.Control.Host.RestartCause";

    std::string service;
    boost::system::error_code ec = ipmi::getService(ctx, restartCauseIntf,
                                                    restartCausePath, service);

    if (!ec)
    {
        ec = ipmi::getDbusProperty(ctx, service, restartCausePath,
                                   restartCauseIntf, "RestartCause",
                                   restartCause);
    }
    if (ec)
    {
        log<level::ERR>("Failed to fetch RestartCause property",
                        entry("ERROR=%s", ec.message().c_str()),
                        entry("PATH=%s", restartCausePath),
                        entry("INTERFACE=%s", restartCauseIntf));
        return false;
    }
    return true;
}

static bool checkIPMIRestartCause(ipmi::Context::ptr& ctx,
                                  bool& ipmiRestartCause)
{
    std::string restartCause;
    if (!getRestartCause(ctx, restartCause))
    {
        return false;
    }
    ipmiRestartCause =
        (restartCause ==
         "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand");
    return true;
}

//----------------------------------------------------------------------
// Get Chassis Status commands
//----------------------------------------------------------------------
ipmi::RspType<bool,    // Power is on
              bool,    // Power overload
              bool,    // Interlock
              bool,    // power fault
              bool,    // power control fault
              uint2_t, // power restore policy
              bool,    // reserved

              bool,    // AC failed
              bool,    // last power down caused by a Power overload
              bool,    // last power down caused by a power interlock
              bool,    // last power down caused by power fault
              bool, // last ‘Power is on’ state was entered via IPMI command
              uint3_t, // reserved

              bool,    // Chassis intrusion active
              bool,    // Front Panel Lockout active
              bool,    // Drive Fault
              bool,    // Cooling/fan fault detected
              uint2_t, // Chassis Identify State
              bool,    // Chassis Identify command and state info supported
              bool,    // reserved

              bool,    // Power off button disabled
              bool,    // Reset button disabled
              bool,    // Diagnostic Interrupt button disabled
              bool,    // Standby (sleep) button disabled
              bool,    // Power off button disable allowed
              bool,    // Reset button disable allowed
              bool,    // Diagnostic Interrupt button disable allowed
              bool     // Standby (sleep) button disable allowed
              >
    ipmiGetChassisStatus(ipmi::Context::ptr ctx)
{
    std::optional<uint2_t> restorePolicy =
        power_policy::getPowerRestorePolicy();
    std::optional<bool> powerGood = power_policy::getPowerStatus();
    if (!restorePolicy || !powerGood)
    {
        return ipmi::responseUnspecifiedError();
    }

    //  Front Panel Button Capabilities and disable/enable status(Optional)
    std::optional<bool> powerButtonReading = getButtonEnabled(powerButtonPath);
    // allow disable if the interface is present
    bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
    // default return the button is enabled (not disabled)
    bool powerButtonDisabled = false;
    if (powerButtonDisableAllow)
    {
        // return the real value of the button status, if present
        powerButtonDisabled = *powerButtonReading;
    }

    std::optional<bool> resetButtonReading = getButtonEnabled(resetButtonPath);
    // allow disable if the interface is present
    bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
    // default return the button is enabled (not disabled)
    bool resetButtonDisabled = false;
    if (resetButtonDisableAllow)
    {
        // return the real value of the button status, if present
        resetButtonDisabled = *resetButtonReading;
    }

    std::optional<bool> interruptButtonReading =
        getButtonEnabled(interruptButtonPath);
    // allow disable if the interface is present
    bool interruptButtonDisableAllow =
        static_cast<bool>(interruptButtonReading);
    // default return the button is enabled (not disabled)
    bool interruptButtonDisabled = false;
    if (interruptButtonDisableAllow)
    {
        // return the real value of the button status, if present
        interruptButtonDisabled = *interruptButtonReading;
    }

    bool powerDownAcFailed = power_policy::getACFailStatus();

    bool powerStatusIPMI = false;
    if (!checkIPMIRestartCause(ctx, powerStatusIPMI))
    {
        return ipmi::responseUnspecifiedError();
    }

    bool chassisIntrusionActive = false;
    constexpr const char* chassisIntrusionObj =
        "/xyz/openbmc_project/Chassis/Intrusion";
    constexpr const char* chassisIntrusionInf =
        "xyz.openbmc_project.Chassis.Intrusion";

    std::string intrusionService;
    boost::system::error_code ec = ipmi::getService(
        ctx, chassisIntrusionInf, chassisIntrusionObj, intrusionService);
    if (ec)
    {
        log<level::ERR>("Failed to get Chassis Intrusion service",
                        entry("ERROR=%s", ec.message().c_str()));
    }

    chassisIntrusionActive = !intrusionService.empty();

    // This response has a lot of hard-coded, unsupported fields
    // They are set to false or 0
    constexpr bool powerOverload = false;
    constexpr bool chassisInterlock = false;
    constexpr bool powerFault = false;
    constexpr bool powerControlFault = false;
    constexpr bool powerDownOverload = false;
    constexpr bool powerDownInterlock = false;
    constexpr bool powerDownPowerFault = false;
    constexpr bool frontPanelLockoutActive = false;
    constexpr bool driveFault = false;
    constexpr bool coolingFanFault = false;
    // chassisIdentifySupport set because this command is implemented
    constexpr bool chassisIdentifySupport = true;
    uint2_t chassisIdentifyState = types::enum_cast<uint2_t>(chassisIDState);
    constexpr bool sleepButtonDisabled = false;
    constexpr bool sleepButtonDisableAllow = false;

    return ipmi::responseSuccess(
        *powerGood, powerOverload, chassisInterlock, powerFault,
        powerControlFault, *restorePolicy,
        false, // reserved

        powerDownAcFailed, powerDownOverload, powerDownInterlock,
        powerDownPowerFault, powerStatusIPMI,
        uint3_t(0), // reserved

        chassisIntrusionActive, frontPanelLockoutActive, driveFault,
        coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
        false, // reserved

        powerButtonDisabled, resetButtonDisabled, interruptButtonDisabled,
        sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
        interruptButtonDisableAllow, sleepButtonDisableAllow);
}

static uint4_t getRestartCauseValue(const std::string& cause)
{
    uint4_t restartCauseValue = 0;
    if (cause == "xyz.openbmc_project.State.Host.RestartCause.Unknown")
    {
        restartCauseValue = 0x0;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.IpmiCommand")
    {
        restartCauseValue = 0x1;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.ResetButton")
    {
        restartCauseValue = 0x2;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PowerButton")
    {
        restartCauseValue = 0x3;
    }
    else if (cause ==
             "xyz.openbmc_project.State.Host.RestartCause.WatchdogTimer")
    {
        restartCauseValue = 0x4;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.OEM")
    {
        restartCauseValue = 0x5;
    }
    else if (cause ==
             "xyz.openbmc_project.State.Host.RestartCause.PowerPolicyAlwaysOn")
    {
        restartCauseValue = 0x6;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause."
                      "PowerPolicyPreviousState")
    {
        restartCauseValue = 0x7;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.PEFReset")
    {
        restartCauseValue = 0x8;
    }
    else if (cause ==
             "xyz.openbmc_project.State.Host.RestartCause.PEFPowerCycle")
    {
        restartCauseValue = 0x9;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.SoftReset")
    {
        restartCauseValue = 0xa;
    }
    else if (cause == "xyz.openbmc_project.State.Host.RestartCause.RTCWakeup")
    {
        restartCauseValue = 0xb;
    }
    return restartCauseValue;
}

ipmi::RspType<uint4_t, // Restart Cause
              uint4_t, // reserved
              uint8_t  // channel number
              >
    ipmiGetSystemRestartCause(ipmi::Context::ptr ctx)
{
    std::string restartCauseStr;
    if (!getRestartCause(ctx, restartCauseStr))
    {
        return ipmi::responseUnspecifiedError();
    }
    constexpr uint4_t reserved = 0;
    auto channel = static_cast<uint8_t>(ctx->channel);
    return ipmi::responseSuccess(getRestartCauseValue(restartCauseStr),
                                 reserved, channel);
}

ipmi::RspType<> ipmiSetFrontPanelButtonEnables(
    bool disablePowerButton, bool disableResetButton,
    bool disableInterruptButton, [[maybe_unused]] bool disableSleepButton,
    uint4_t reserved)
{
    if (reserved)
    {
        return ipmi::responseInvalidFieldRequest();
    }
    bool error = false;

    error |= setButtonEnabled(powerButtonPath, disablePowerButton);
    error |= setButtonEnabled(resetButtonPath, disableResetButton);
    error |= setButtonEnabled(interruptButtonPath, disableInterruptButton);

    if (error)
    {
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess();
}

static void registerChassisFunctions(void)
{
    log<level::INFO>("Registering Chassis commands");

    createIdentifyTimer();

    if (matchPtr == nullptr)
    {
        using namespace sdbusplus::bus::match::rules;
        auto bus = getSdBus();

        matchPtr = std::make_unique<sdbusplus::bus::match_t>(
            *bus,
            sdbusplus::bus::match::rules::propertiesChanged(idButtonPath,
                                                            buttonIntf),
            std::bind(idButtonPropChanged, std::placeholders::_1));
    }

    // <Chassis Identify>
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                          ipmi::chassis::cmdChassisIdentify,
                          ipmi::Privilege::Operator, ipmiChassisIdentify);
    // <Get Chassis Status>
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                          ipmi::chassis::cmdGetChassisStatus,
                          ipmi::Privilege::User, ipmiGetChassisStatus);
    // <Get System Restart Cause>
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                          ipmi::chassis::cmdGetSystemRestartCause,
                          ipmi::Privilege::User, ipmiGetSystemRestartCause);
    // <Set Front Panel Enables>
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::netFnChassis,
                          ipmi::chassis::cmdSetFrontPanelButtonEnables,
                          ipmi::Privilege::Admin,
                          ipmiSetFrontPanelButtonEnables);
}

} // namespace ipmi::chassis
