/**
 * 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 "config.h"

#include "utils.hpp"

#include "utility.hpp"

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

#include <cassert>
#include <exception>
#include <filesystem>
#include <format>
#include <iomanip>
#include <ios>
#include <iostream>
#include <regex>
#include <sstream>
#include <stdexcept>

using namespace phosphor::logging;
using namespace phosphor::power::util;
using namespace sdbusplus::xyz::openbmc_project::Common::Device::Error;
namespace fs = std::filesystem;

namespace utils
{

constexpr auto IBMCFFPSInterface =
    "xyz.openbmc_project.Configuration.IBMCFFPSConnector";
constexpr auto i2cBusProp = "I2CBus";
constexpr auto i2cAddressProp = "I2CAddress";

PsuI2cInfo getPsuI2c(sdbusplus::bus_t& bus, const std::string& psuInventoryPath)
{
    auto depth = 0;
    auto objects = getSubTree(bus, "/", IBMCFFPSInterface, depth);
    if (objects.empty())
    {
        throw std::runtime_error("Supported Configuration Not Found");
    }

    std::optional<std::uint64_t> i2cbus;
    std::optional<std::uint64_t> i2caddr;

    // GET a map of objects back.
    // Each object will have a path, a service, and an interface.
    for (const auto& [path, services] : objects)
    {
        auto service = services.begin()->first;

        if (path.empty() || service.empty())
        {
            continue;
        }

        // Match the PSU identifier in the path with the passed PSU inventory
        // path. Compare the last character of both paths to find the PSU bus
        // and address. example: PSU path:
        // /xyz/openbmc_project/inventory/system/board/Nisqually_Backplane/Power_Supply_Slot_0
        // PSU inventory path:
        // /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0
        if (path.back() == psuInventoryPath.back())
        {
            // Retrieve i2cBus and i2cAddress from array of properties.
            auto properties =
                getAllProperties(bus, path, IBMCFFPSInterface, service);
            for (const auto& property : properties)
            {
                try
                {
                    if (property.first == i2cBusProp)
                    {
                        i2cbus = std::get<uint64_t>(properties.at(i2cBusProp));
                    }
                    else if (property.first == i2cAddressProp)
                    {
                        i2caddr =
                            std::get<uint64_t>(properties.at(i2cAddressProp));
                    }
                }
                catch (const std::exception& e)
                {
                    log<level::WARNING>(
                        std::format("Error reading property {}: {}",
                                    property.first, e.what())
                            .c_str());
                }
            }

            if (i2cbus.has_value() && i2caddr.has_value())
            {
                break;
            }
        }
    }

    if (!i2cbus.has_value() || !i2caddr.has_value())
    {
        throw std::runtime_error("Failed to get I2C bus or address");
    }

    return std::make_tuple(*i2cbus, *i2caddr);
}

std::unique_ptr<phosphor::pmbus::PMBusBase>
    getPmbusIntf(std::uint64_t i2cBus, std::uint64_t i2cAddr)
{
    std::stringstream ss;
    ss << std::hex << std::setw(4) << std::setfill('0') << i2cAddr;
    return phosphor::pmbus::createPMBus(i2cBus, ss.str());
}

std::string readVPDValue(phosphor::pmbus::PMBusBase& pmbusIntf,
                         const std::string& vpdName,
                         const phosphor::pmbus::Type& type,
                         const std::size_t& vpdSize)
{
    std::string vpdValue;
    const std::regex illegalVPDRegex =
        std::regex("[^[:alnum:]]", std::regex::basic);

    try
    {
        vpdValue = pmbusIntf.readString(vpdName, type);
    }
    catch (const ReadFailure& e)
    {
        // Ignore the read failure, let pmbus code indicate failure.
    }

    if (vpdValue.size() != vpdSize)
    {
        log<level::INFO>(
            std::format(" {} resize needed. size: {}", vpdName, vpdValue.size())
                .c_str());
        vpdValue.resize(vpdSize, ' ');
    }

    // Replace any illegal values with space(s).
    std::regex_replace(vpdValue.begin(), vpdValue.begin(), vpdValue.end(),
                       illegalVPDRegex, " ");

    return vpdValue;
}

bool checkFileExists(const std::string& filePath)
{
    try
    {
        return std::filesystem::exists(filePath);
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(std::format("Unable to check for existence of {}: {}",
                                    filePath, e.what())
                            .c_str());
    }
    return false;
}

std::string getDeviceName(std::string devPath)
{
    if (devPath.back() == '/')
    {
        devPath.pop_back();
    }
    return fs::path(devPath).stem().string();
}

std::string getDevicePath(sdbusplus::bus_t& bus,
                          const std::string& psuInventoryPath)
{
    try
    {
        if (usePsuJsonFile())
        {
            auto data = loadJSONFromFile(PSU_JSON_PATH);
            if (data == nullptr)
            {
                return {};
            }
            auto devicePath = data["psuDevices"][psuInventoryPath];
            if (devicePath.empty())
            {
                log<level::WARNING>("Unable to find psu devices or path");
            }
            return devicePath;
        }
        else
        {
            const auto [i2cbus, i2caddr] = getPsuI2c(bus, psuInventoryPath);
            const auto DevicePath = "/sys/bus/i2c/devices/";
            std::ostringstream ss;
            ss << std::hex << std::setw(4) << std::setfill('0') << i2caddr;
            std::string addrStr = ss.str();
            std::string busStr = std::to_string(i2cbus);
            std::string devPath = DevicePath + busStr + "-" + addrStr;
            return devPath;
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(
            std::format("Error in getDevicePath: {}", e.what()).c_str());
        return {};
    }
    catch (...)
    {
        log<level::ERR>("Unknown error occurred in getDevicePath");
        return {};
    }
}

std::pair<uint8_t, uint8_t> parseDeviceName(const std::string& devName)
{
    // Get I2C bus and device address, e.g. 3-0068
    // is parsed to bus 3, device address 0x68
    auto pos = devName.find('-');
    assert(pos != std::string::npos);
    uint8_t busId = std::stoi(devName.substr(0, pos));
    uint8_t devAddr = std::stoi(devName.substr(pos + 1), nullptr, 16);
    return {busId, devAddr};
}

bool usePsuJsonFile()
{
    return checkFileExists(PSU_JSON_PATH);
}

} // namespace utils
