/**
 * 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 "types.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 <chrono>
#include <fstream>
#include <map>
#include <span>
#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_t& 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();
}

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_t& 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.
    }
}

bool UCD90320Monitor::isPresent(const std::string& inventoryPath)
{
    // Empty path indicates no presence check is needed
    if (inventoryPath.empty())
    {
        return true;
    }

    // Get presence from D-Bus interface/property
    try
    {
        bool present{true};
        util::getProperty(INVENTORY_IFACE, PRESENT_PROP, inventoryPath,
                          INVENTORY_MGR_IFACE, bus, present);
        log<level::INFO>(
            fmt::format("Presence, path: {}, value: {}", inventoryPath, present)
                .c_str());
        return present;
    }
    catch (const std::exception& e)
    {
        log<level::INFO>(
            fmt::format("Error getting presence property, path: {}, error: {}",
                        inventoryPath, e.what())
                .c_str());
        return false;
    }
}

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)
            {
                auto nameIterator = railElement.find("name");

                if (nameIterator != railElement.end())
                {
                    Rail rail;
                    rail.name = (*nameIterator).get<std::string>();

                    // Presence element is optional
                    auto presenceIterator = railElement.find("presence");
                    if (presenceIterator != railElement.end())
                    {
                        rail.presence = (*presenceIterator).get<std::string>();
                    }

                    log<level::DEBUG>(
                        fmt::format("Adding rail, name: {}, presence: {}",
                                    rail.name, rail.presence)
                            .c_str());
                    rails.emplace_back(std::move(rail));
                }
                else
                {
                    log<level::ERR>(
                        fmt::format(
                            "No name found within rail in configuration file: {}",
                            pathName.string())
                            .c_str());
                }
            }
        }
        else
        {
            log<level::ERR>(
                fmt::format("No rails found in configuration file: {}",
                            pathName.string())
                    .c_str());
        }
        log<level::DEBUG>(
            fmt::format("Found number of rails: {}", rails.size()).c_str());

        // 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())
                {
                    Pin pin;
                    pin.name = (*nameIterator).get<std::string>();
                    pin.line = (*lineIterator).get<unsigned int>();

                    // Presence element is optional
                    auto presenceIterator = pinElement.find("presence");
                    if (presenceIterator != pinElement.end())
                    {
                        pin.presence = (*presenceIterator).get<std::string>();
                    }

                    log<level::DEBUG>(
                        fmt::format(
                            "Adding pin, name: {}, line: {}, presence: {}",
                            pin.name, pin.line, pin.presence)
                            .c_str());
                    pins.emplace_back(std::move(pin));
                }
                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: {}", pins.size()).c_str());
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Error parsing configuration file, error: {}", e.what())
                .c_str());
    }
}

void UCD90320Monitor::onFailure(bool timeout,
                                const std::string& powerSupplyError)
{
    // Wait before reading device data. This is to allow the
    // power supplies and other hardware time to complete failure processing.
    std::this_thread::sleep_for(std::chrono::seconds(7));

    std::string message;
    std::map<std::string, std::string> additionalData{};

    try
    {
        onFailureCheckRails(message, additionalData, powerSupplyError);
        onFailureCheckPins(message, additionalData);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Error when collecting metadata, error: {}", e.what())
                .c_str());
        additionalData.emplace("ERROR", e.what());
    }

    if (message.empty())
    {
        // Could not isolate, but we know something failed, so issue a timeout
        // or generic power good error
        message = timeout ? "xyz.openbmc_project.Power.Error.PowerOnTimeout"
                          : "xyz.openbmc_project.Power.Error.Shutdown";
    }
    logError(message, additionalData);
    if (!timeout)
    {
        createBmcDump();
    }
}

void UCD90320Monitor::onFailureCheckPins(
    std::string& message, std::map<std::string, std::string>& additionalData)
{
    // Setup a list of all the GPIOs on the chip
    gpiod::chip chip{"ucd90320", gpiod::chip::OPEN_BY_LABEL};
    log<level::INFO>(fmt::format("GPIO chip name: {}", chip.name()).c_str());
    log<level::INFO>(fmt::format("GPIO chip label: {}", chip.label()).c_str());
    unsigned int numberLines = chip.num_lines();
    log<level::INFO>(
        fmt::format("GPIO chip number of lines: {}", numberLines).c_str());

    // Workaround libgpiod bulk line maximum by getting values from individual
    // lines
    std::vector<int> values;
    try
    {
        for (unsigned int offset = 0; offset < numberLines; ++offset)
        {
            gpiod::line line = chip.get_line(offset);
            line.request({"phosphor-power-control",
                          gpiod::line_request::DIRECTION_INPUT, 0});
            values.push_back(line.get_value());
            line.release();
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Error reading device GPIOs, error: {}", e.what())
                .c_str());
        additionalData.emplace("GPIO_ERROR", e.what());
    }

    // Add GPIO values to additional data, device has 84 GPIO pins so that value
    // is expected
    if (numberLines == 84 && values.size() >= 84)
    {
        log<level::INFO>(fmt::format("MAR01-24 GPIO values: {}",
                                     std::span{values}.subspan(0, 24))
                             .c_str());
        additionalData.emplace(
            "MAR01_24_GPIO_VALUES",
            fmt::format("{}", std::span{values}.subspan(0, 24)));
        log<level::INFO>(fmt::format("EN1-32 GPIO values: {}",
                                     std::span{values}.subspan(24, 32))
                             .c_str());
        additionalData.emplace(
            "EN1_32_GPIO_VALUES",
            fmt::format("{}", std::span{values}.subspan(24, 32)));
        log<level::INFO>(fmt::format("LGP01-16 GPIO values: {}",
                                     std::span{values}.subspan(56, 16))
                             .c_str());
        additionalData.emplace(
            "LGP01_16_GPIO_VALUES",
            fmt::format("{}", std::span{values}.subspan(56, 16)));
        log<level::INFO>(fmt::format("DMON1-8 GPIO values: {}",
                                     std::span{values}.subspan(72, 8))
                             .c_str());
        additionalData.emplace(
            "DMON1_8_GPIO_VALUES",
            fmt::format("{}", std::span{values}.subspan(72, 8)));
        log<level::INFO>(fmt::format("GPIO1-4 GPIO values: {}",
                                     std::span{values}.subspan(80, 4))
                             .c_str());
        additionalData.emplace(
            "GPIO1_4_GPIO_VALUES",
            fmt::format("{}", std::span{values}.subspan(80, 4)));
    }
    else
    {
        log<level::INFO>(fmt::format("GPIO values: {}", values).c_str());
        additionalData.emplace("GPIO_VALUES", fmt::format("{}", values));
    }

    // Only check GPIOs if no rail fail was found
    if (message.empty())
    {
        for (size_t pin = 0; pin < pins.size(); ++pin)
        {
            unsigned int line = pins[pin].line;
            if (line < values.size())
            {
                int value = values[line];

                if ((value == 0) && isPresent(pins[pin].presence))
                {
                    additionalData.emplace("INPUT_NUM",
                                           fmt::format("{}", line));
                    additionalData.emplace("INPUT_NAME", pins[pin].name);
                    message =
                        "xyz.openbmc_project.Power.Error.PowerSequencerPGOODFault";
                    return;
                }
            }
        }
    }
}

void UCD90320Monitor::onFailureCheckRails(
    std::string& message, std::map<std::string, std::string>& additionalData,
    const std::string& powerSupplyError)
{
    auto statusWord = readStatusWord();
    additionalData.emplace("STATUS_WORD", fmt::format("{:#06x}", statusWord));
    try
    {
        additionalData.emplace("MFR_STATUS",
                               fmt::format("{:#014x}", readMFRStatus()));
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            fmt::format("Error when collecting MFR_STATUS, error: {}", e.what())
                .c_str());
        additionalData.emplace("ERROR", e.what());
    }

    // The status_word register has a summary bit to tell us if each page even
    // needs to be checked
    if (statusWord & status_word::VOUT_FAULT)
    {
        constexpr size_t numberPages = 32;
        for (size_t page = 0; page < numberPages; page++)
        {
            auto statusVout = pmbusInterface.insertPageNum(STATUS_VOUT, page);
            if (pmbusInterface.exists(statusVout, Type::Debug))
            {
                uint8_t vout = pmbusInterface.read(statusVout, Type::Debug);

                if (vout)
                {
                    // If any bits are on log them, though some are just
                    // warnings so they won't cause errors
                    log<level::INFO>(
                        fmt::format("{}, value: {:#04x}", statusVout, vout)
                            .c_str());

                    // Log errors if any non-warning bits on
                    if (vout & ~status_vout::WARNING_MASK)
                    {
                        additionalData.emplace(
                            fmt::format("STATUS{}_VOUT", page),
                            fmt::format("{:#04x}", vout));

                        // Base the callouts on the first present vout failure
                        // found
                        if (message.empty() && (page < rails.size()) &&
                            isPresent(rails[page].presence))
                        {
                            additionalData.emplace("RAIL_NAME",
                                                   rails[page].name);

                            // Use power supply error if set and 12v rail has
                            // failed, else use voltage error
                            message =
                                ((page == 0) && !powerSupplyError.empty())
                                    ? powerSupplyError
                                    : "xyz.openbmc_project.Power.Error.PowerSequencerVoltageFault";
                        }
                    }
                }
            }
        }
    }
    // If no vout failure found, but power supply error is set, use power supply
    // error
    if (message.empty())
    {
        message = powerSupplyError;
    }
}

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

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

} // namespace phosphor::power::sequencer
