/**
 * Copyright © 2024 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 "rail.hpp"

#include "pmbus.hpp"
#include "power_sequencer_device.hpp"

#include <exception>
#include <format>

namespace phosphor::power::sequencer
{
namespace status_vout = phosphor::pmbus::status_vout;

bool Rail::isPresent(Services& services)
{
    // Initially assume rail is present
    bool present{true};

    // If presence data member contains an inventory path to check
    if (presence)
    {
        const std::string& inventoryPath = *presence;
        try
        {
            present = services.isPresent(inventoryPath);
        }
        catch (const std::exception& e)
        {
            throw std::runtime_error{std::format(
                "Unable to determine presence of rail {} using inventory path {}: {}",
                name, inventoryPath, e.what())};
        }
    }

    return present;
}

uint16_t Rail::getStatusWord(PowerSequencerDevice& device)
{
    uint16_t value{0};
    try
    {
        verifyHasPage();
        value = device.getStatusWord(*page);
    }
    catch (const std::exception& e)
    {
        throw std::runtime_error{
            std::format("Unable to read STATUS_WORD value for rail {}: {}",
                        name, e.what())};
    }
    return value;
}

uint8_t Rail::getStatusVout(PowerSequencerDevice& device)
{
    uint8_t value{0};
    try
    {
        verifyHasPage();
        value = device.getStatusVout(*page);
    }
    catch (const std::exception& e)
    {
        throw std::runtime_error{
            std::format("Unable to read STATUS_VOUT value for rail {}: {}",
                        name, e.what())};
    }
    return value;
}

double Rail::getReadVout(PowerSequencerDevice& device)
{
    double value{0.0};
    try
    {
        verifyHasPage();
        value = device.getReadVout(*page);
    }
    catch (const std::exception& e)
    {
        throw std::runtime_error{std::format(
            "Unable to read READ_VOUT value for rail {}: {}", name, e.what())};
    }
    return value;
}

double Rail::getVoutUVFaultLimit(PowerSequencerDevice& device)
{
    double value{0.0};
    try
    {
        verifyHasPage();
        value = device.getVoutUVFaultLimit(*page);
    }
    catch (const std::exception& e)
    {
        throw std::runtime_error{std::format(
            "Unable to read VOUT_UV_FAULT_LIMIT value for rail {}: {}", name,
            e.what())};
    }
    return value;
}

bool Rail::hasPgoodFault(PowerSequencerDevice& device, Services& services,
                         const std::vector<int>& gpioValues,
                         std::map<std::string, std::string>& additionalData)
{
    return (hasPgoodFaultStatusVout(device, services, additionalData) ||
            hasPgoodFaultGPIO(device, services, gpioValues, additionalData) ||
            hasPgoodFaultOutputVoltage(device, services, additionalData));
}

bool Rail::hasPgoodFaultStatusVout(
    PowerSequencerDevice& device, Services& services,
    std::map<std::string, std::string>& additionalData)
{
    bool hasFault{false};

    // If rail is present and we are checking the value of STATUS_VOUT
    if (isPresent(services) && checkStatusVout)
    {
        // Read STATUS_VOUT value from device
        uint8_t statusVout = getStatusVout(device);

        // Check if fault (non-warning) bits are set in value
        if (statusVout & ~status_vout::WARNING_MASK)
        {
            hasFault = true;
            services.logErrorMsg(std::format(
                "Rail {} has fault bits set in STATUS_VOUT: {:#04x}", name,
                statusVout));
            additionalData.emplace("STATUS_VOUT",
                                   std::format("{:#04x}", statusVout));
            storePgoodFaultDebugData(device, services, additionalData);
        }
        else if (statusVout != 0)
        {
            services.logInfoMsg(std::format(
                "Rail {} has warning bits set in STATUS_VOUT: {:#04x}", name,
                statusVout));
        }
    }

    return hasFault;
}

bool Rail::hasPgoodFaultGPIO(PowerSequencerDevice& device, Services& services,
                             const std::vector<int>& gpioValues,
                             std::map<std::string, std::string>& additionalData)
{
    bool hasFault{false};

    // If rail is present and a GPIO is defined for checking pgood status
    if (isPresent(services) && gpio)
    {
        // Get GPIO value
        unsigned int line = gpio->line;
        bool activeLow = gpio->activeLow;
        if (line >= gpioValues.size())
        {
            throw std::runtime_error{std::format(
                "Invalid GPIO line offset {} for rail {}: Device only has {} GPIO values",
                line, name, gpioValues.size())};
        }
        int value = gpioValues[line];

        // Check if value indicates pgood signal is not active
        if ((activeLow && (value == 1)) || (!activeLow && (value == 0)))
        {
            hasFault = true;
            services.logErrorMsg(std::format(
                "Rail {} pgood GPIO line offset {} has inactive value {}", name,
                line, value));
            additionalData.emplace("GPIO_LINE", std::format("{}", line));
            additionalData.emplace("GPIO_VALUE", std::format("{}", value));
            storePgoodFaultDebugData(device, services, additionalData);
        }
    }

    return hasFault;
}

bool Rail::hasPgoodFaultOutputVoltage(
    PowerSequencerDevice& device, Services& services,
    std::map<std::string, std::string>& additionalData)
{
    bool hasFault{false};

    // If rail is present and we are comparing output voltage to UV limit
    if (isPresent(services) && compareVoltageToLimit)
    {
        // Read output voltage and UV fault limit values from device
        double vout = getReadVout(device);
        double uvLimit = getVoutUVFaultLimit(device);

        // If output voltage is at or below UV fault limit
        if (vout <= uvLimit)
        {
            hasFault = true;
            services.logErrorMsg(std::format(
                "Rail {} output voltage {}V is <= UV fault limit {}V", name,
                vout, uvLimit));
            additionalData.emplace("READ_VOUT", std::format("{}", vout));
            additionalData.emplace("VOUT_UV_FAULT_LIMIT",
                                   std::format("{}", uvLimit));
            storePgoodFaultDebugData(device, services, additionalData);
        }
    }

    return hasFault;
}

void Rail::verifyHasPage()
{
    if (!page)
    {
        throw std::runtime_error{
            std::format("No PAGE number defined for rail {}", name)};
    }
}

void Rail::storePgoodFaultDebugData(
    PowerSequencerDevice& device, Services& services,
    std::map<std::string, std::string>& additionalData)
{
    services.logErrorMsg(std::format("Pgood fault detected in rail {}", name));
    additionalData.emplace("RAIL_NAME", name);
    if (page)
    {
        try
        {
            uint16_t statusWord = getStatusWord(device);
            services.logInfoMsg(
                std::format("Rail {} STATUS_WORD: {:#06x}", name, statusWord));
            additionalData.emplace("STATUS_WORD",
                                   std::format("{:#06x}", statusWord));
        }
        catch (...)
        {
            // Ignore error; don't interrupt pgood fault handling
        }
    }
}

} // namespace phosphor::power::sequencer
