/**
 * Copyright © 2021 IBM 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 "ucd90320_monitor.hpp"

#include "utility.hpp"

#include <fmt/format.h>
#include <fmt/ranges.h>

#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Common/Device/error.hpp>

#include <fstream>
#include <map>
#include <string>

namespace phosphor::power::sequencer
{

using json = nlohmann::json;
using namespace pmbus;
using namespace phosphor::logging;
using namespace phosphor::power;

const std::string compatibleInterface =
    "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
const std::string compatibleNamesProperty = "Names";

namespace device_error = sdbusplus::xyz::openbmc_project::Common::Device::Error;

UCD90320Monitor::UCD90320Monitor(sdbusplus::bus::bus& bus, std::uint8_t i2cBus,
                                 std::uint16_t i2cAddress) :
    PowerSequencerMonitor(bus),
    match{bus,
          sdbusplus::bus::match::rules::interfacesAdded() +
              sdbusplus::bus::match::rules::sender(
                  "xyz.openbmc_project.EntityManager"),
          std::bind(&UCD90320Monitor::interfacesAddedHandler, this,
                    std::placeholders::_1)},
    pmbusInterface{
        fmt::format("/sys/bus/i2c/devices/{}-{:04x}", i2cBus, i2cAddress)
            .c_str(),
        "ucd9000", 0}

{
    // Use the compatible system types information, if already available, to
    // load the configuration file
    findCompatibleSystemTypes();
}

bool UCD90320Monitor::checkPGOODFaults(
    std::map<std::string, std::string>& additionalData)
{
    // Check only the GPIs configured on this system.
    std::vector<int> values = lines.get_values();

    bool errorCreated = false;
    for (size_t pin = 0; pin < pins.size(); ++pin)
    {
        if (pin < values.size() && !values[pin])
        {
            try
            {
                additionalData.emplace(
                    "STATUS_WORD", fmt::format("{:#04x}", readStatusWord()));
                additionalData.emplace("MFR_STATUS",
                                       fmt::format("{:#04x}", readMFRStatus()));
            }
            catch (device_error::ReadFailure& e)
            {
                log<level::ERR>("ReadFailure when collecting metadata");
            }
            additionalData.emplace("INPUT_NUM",
                                   fmt::format("{}", pins[pin].line));
            additionalData.emplace("INPUT_NAME", pins[pin].name);
            additionalData.emplace("INPUT_STATUS",
                                   fmt::format("{}", values[pin]));

            logError("xyz.openbmc_project.Power.Error.PowerSequencerPGOODFault",
                     additionalData);

            errorCreated = true;
            break;
        }
    }
    return errorCreated;
}

bool UCD90320Monitor::checkVOUTFaults(
    std::map<std::string, std::string>& additionalData)
{
    // The status_word register has a summary bit to tell us
    // if each page even needs to be checked
    auto statusWord = readStatusWord();
    if (!(statusWord & status_word::VOUT_FAULT))
    {
        return false;
    }

    constexpr size_t numberPages = 24;
    bool errorCreated = false;
    for (size_t page = 0; page < numberPages; page++)
    {
        auto statusVout = pmbusInterface.insertPageNum(STATUS_VOUT, page);
        uint8_t vout = pmbusInterface.read(statusVout, Type::Debug);

        // If any bits are on log them, though some are just
        // warnings so they won't cause errors
        if (vout)
        {
            log<level::INFO>("A voltage rail has bits on in STATUS_VOUT",
                             entry("STATUS_VOUT=0x%X", vout),
                             entry("PAGE=%d", page));
        }

        // Log errors if any non-warning bits on
        if (vout & ~status_vout::WARNING_MASK)
        {
            auto railName = rails[page];

            additionalData.emplace("STATUS_WORD",
                                   fmt::format("{:#04x}", statusWord));
            additionalData.emplace("STATUS_VOUT", fmt::format("{:#02x}", vout));
            try
            {
                additionalData.emplace("MFR_STATUS",
                                       fmt::format("{:#04x}", readMFRStatus()));
            }
            catch (device_error::ReadFailure& e)
            {
                log<level::ERR>("ReadFailure when collecting MFR_STATUS");
            }
            additionalData.emplace("RAIL", fmt::format("{}", page));
            additionalData.emplace("RAIL_NAME", railName);

            logError(
                "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault",
                additionalData);

            errorCreated = true;
            break;
        }
    }

    return errorCreated;
}

void UCD90320Monitor::findCompatibleSystemTypes()
{
    try
    {
        auto subTree = util::getSubTree(bus, "/xyz/openbmc_project/inventory",
                                        compatibleInterface, 0);

        auto objectIt = subTree.cbegin();
        if (objectIt != subTree.cend())
        {
            const auto& objPath = objectIt->first;

            // Get the first service name
            auto serviceIt = objectIt->second.cbegin();
            if (serviceIt != objectIt->second.cend())
            {
                std::string service = serviceIt->first;
                if (!service.empty())
                {
                    std::vector<std::string> compatibleSystemTypes;

                    // Get compatible system types property value
                    util::getProperty(compatibleInterface,
                                      compatibleNamesProperty, objPath, service,
                                      bus, compatibleSystemTypes);

                    log<level::DEBUG>(
                        fmt::format("Found compatible systems: {}",
                                    compatibleSystemTypes)
                            .c_str());
                    // Use compatible systems information to find config file
                    findConfigFile(compatibleSystemTypes);
                }
            }
        }
    }
    catch (const std::exception&)
    {
        // Compatible system types information is not available.
    }
}

void UCD90320Monitor::findConfigFile(
    const std::vector<std::string>& compatibleSystemTypes)
{
    // Expected config file path name:
    // /usr/share/phosphor-power-sequencer/UCD90320Monitor_<systemType>.json

    // Add possible file names based on compatible system types (if any)
    for (const std::string& systemType : compatibleSystemTypes)
    {
        // Check if file exists
        std::filesystem::path pathName{
            "/usr/share/phosphor-power-sequencer/UCD90320Monitor_" +
            systemType + ".json"};
        if (std::filesystem::exists(pathName))
        {
            log<level::INFO>(
                fmt::format("Config file path: {}", pathName.string()).c_str());
            parseConfigFile(pathName);
            break;
        }
    }
}

void UCD90320Monitor::interfacesAddedHandler(sdbusplus::message::message& msg)
{
    // Only continue if message is valid and rails / pins have not already been
    // found
    if (!msg || !rails.empty())
    {
        return;
    }

    try
    {
        // Read the dbus message
        sdbusplus::message::object_path objPath;
        std::map<std::string,
                 std::map<std::string, std::variant<std::vector<std::string>>>>
            interfaces;
        msg.read(objPath, interfaces);

        // Find the compatible interface, if present
        auto itIntf = interfaces.find(compatibleInterface);
        if (itIntf != interfaces.cend())
        {
            // Find the Names property of the compatible interface, if present
            auto itProp = itIntf->second.find(compatibleNamesProperty);
            if (itProp != itIntf->second.cend())
            {
                // Get value of Names property
                const auto& propValue = std::get<0>(itProp->second);
                if (!propValue.empty())
                {
                    log<level::INFO>(
                        fmt::format(
                            "InterfacesAdded for compatible systems: {}",
                            propValue)
                            .c_str());

                    // Use compatible systems information to find config file
                    findConfigFile(propValue);
                }
            }
        }
    }
    catch (const std::exception&)
    {
        // Error trying to read interfacesAdded message.
    }
}

void UCD90320Monitor::parseConfigFile(const std::filesystem::path& pathName)
{
    try
    {
        std::ifstream file{pathName};
        json rootElement = json::parse(file);

        // Parse rail information from config file
        auto railsIterator = rootElement.find("rails");
        if (railsIterator != rootElement.end())
        {
            for (const auto& railElement : *railsIterator)
            {
                std::string rail = railElement.get<std::string>();
                rails.emplace_back(std::move(rail));
            }
        }
        else
        {
            log<level::ERR>(
                fmt::format("No rails found in configuration file: {}",
                            pathName.string())
                    .c_str());
        }
        log<level::DEBUG>(fmt::format("Found rails: {}", rails).c_str());

        // List of line offsets for libgpiod
        std::vector<unsigned int> offsets;

        // Parse pin information from config file
        auto pinsIterator = rootElement.find("pins");
        if (pinsIterator != rootElement.end())
        {
            for (const auto& pinElement : *pinsIterator)
            {
                auto nameIterator = pinElement.find("name");
                auto lineIterator = pinElement.find("line");

                if (nameIterator != pinElement.end() &&
                    lineIterator != pinElement.end())
                {
                    std::string name = (*nameIterator).get<std::string>();
                    unsigned int line = (*lineIterator).get<unsigned int>();

                    Pin pin;
                    pin.name = name;
                    pin.line = line;
                    pins.emplace_back(std::move(pin));
                    offsets.emplace_back(line);
                }
                else
                {
                    log<level::ERR>(
                        fmt::format(
                            "No name or line found within pin in configuration file: {}",
                            pathName.string())
                            .c_str());
                }
            }
        }
        else
        {
            log<level::ERR>(
                fmt::format("No pins found in configuration file: {}",
                            pathName.string())
                    .c_str());
        }
        log<level::DEBUG>(
            fmt::format("Found number of pins: {}", rails.size()).c_str());
        setUpGpio(offsets);
    }
    catch (const std::exception& e)
    {
        // Log error message in journal
        log<level::ERR>(std::string("Exception parsing configuration file: " +
                                    std::string(e.what()))
                            .c_str());
    }
}

void UCD90320Monitor::onFailure(bool timeout,
                                const std::string& powerSupplyError)
{
    std::map<std::string, std::string> additionalData{};
    if (!powerSupplyError.empty())
    {
        logError(powerSupplyError, additionalData);
        return;
    }

    try
    {
        bool voutError = checkVOUTFaults(additionalData);
        bool pgoodError = checkPGOODFaults(additionalData);

        // Not a voltage or PGOOD fault, but we know something
        // failed so still create an error log.
        if (!voutError && !pgoodError)
        {
            // Default to generic pgood error
            logError("xyz.openbmc_project.Power.Error.Shutdown",
                     additionalData);
        }
    }
    catch (device_error::ReadFailure& e)
    {
        log<level::ERR>("ReadFailure when collecting metadata");

        if (timeout)
        {
            // Default to timeout error
            logError("xyz.openbmc_project.Power.Error.PowerOnTimeout",
                     additionalData);
        }
        else
        {
            // Default to generic pgood error
            logError("xyz.openbmc_project.Power.Error.Shutdown",
                     additionalData);
        }
    }
}

uint16_t UCD90320Monitor::readStatusWord()
{
    return pmbusInterface.read(STATUS_WORD, Type::Debug);
}

uint32_t UCD90320Monitor::readMFRStatus()
{
    const std::string mfrStatus = "mfr_status";
    return pmbusInterface.read(mfrStatus, Type::HwmonDeviceDebug);
}

void UCD90320Monitor::setUpGpio(const std::vector<unsigned int>& offsets)
{
    gpiod::chip chip{"ucd90320", gpiod::chip::OPEN_BY_LABEL};
    lines = chip.get_lines(offsets);
    lines.request(
        {"phosphor-power-control", gpiod::line_request::DIRECTION_INPUT, 0});
}

} // namespace phosphor::power::sequencer
