/**
 * Copyright © 2020 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 "device_callouts.hpp"

#include "paths.hpp"

#include <fstream>
#include <phosphor-logging/log.hpp>
#include <regex>

namespace openpower::pels::device_callouts
{

constexpr auto debugFilePath = "/etc/phosphor-logging/";
constexpr auto calloutFileSuffix = "_dev_callouts.json";

namespace fs = std::filesystem;
using namespace phosphor::logging;

namespace util
{

fs::path getJSONFilename(const std::vector<std::string>& compatibleList)
{
    std::vector<std::string> names{compatibleList};
    auto basePath = getPELReadOnlyDataPath();
    fs::path fullPath;

    // Find an entry in the list of compatible system names that
    // matches a filename we have.

    // Also match on just _dev_callouts.json, which may be present
    // when it's known that compatibleList won't be correct.
    names.push_back("");

    for (const auto& name : names)
    {
        fs::path filename = name + calloutFileSuffix;

        // Check the debug path first
        fs::path path{fs::path{debugFilePath} / filename};

        if (fs::exists(path))
        {
            log<level::INFO>("Found device callout debug file");
            fullPath = path;
            break;
        }

        path = basePath / filename;

        if (fs::exists(path))
        {
            fullPath = path;
            break;
        }
    }

    if (fullPath.empty())
    {
        throw std::invalid_argument(
            "No JSON dev path callout file for this system");
    }

    return fullPath;
}

/**
 * @brief Reads the callout JSON into an object based on the
 *        compatible system names list.
 *
 * @param[in] compatibleList - The list of compatible names for this
 *                             system.
 *
 * @return nlohmann::json - The JSON object
 */
nlohmann::json loadJSON(const std::vector<std::string>& compatibleList)
{
    auto filename = getJSONFilename(compatibleList);
    std::ifstream file{filename};
    return nlohmann::json::parse(file);
}

std::tuple<size_t, uint8_t> getI2CSearchKeys(const std::string& devPath)
{
    std::smatch match;

    // Look for i2c-A/A-00BB
    // where A = bus number and BB = address
    std::regex regex{"i2c-[0-9]+/([0-9]+)-00([0-9a-f]{2})"};

    regex_search(devPath, match, regex);

    if (match.size() != 3)
    {
        std::string msg = "Could not get I2C bus and address from " + devPath;
        throw std::invalid_argument{msg.c_str()};
    }

    size_t bus = std::stoul(match[1].str(), nullptr, 0);

    // An I2C bus on a CFAM has everything greater than the 10s digit
    // as the CFAM number, so strip it off.  Like:
    //    112 = cfam1 bus 12
    //    1001 = cfam10 bus 1
    bus = bus % 100;

    uint8_t address = std::stoul(match[2].str(), nullptr, 16);

    return {bus, address};
}

std::string getFSISearchKeys(const std::string& devPath)
{
    std::string links;
    std::smatch match;
    auto search = devPath;

    // Look for slave@XX:
    // where XX = link number in hex
    std::regex regex{"slave@([0-9a-f]{2}):"};

    // Find all links in the path and separate them with hyphens.
    while (regex_search(search, match, regex))
    {
        // Convert to an int first to handle a hex number like "0a"
        // though in reality there won't be more than links 0 - 9.
        auto linkNum = std::stoul(match[1].str(), nullptr, 16);
        links += std::to_string(linkNum) + '-';

        search = match.suffix();
    }

    if (links.empty())
    {
        std::string msg = "Could not get FSI links from " + devPath;
        throw std::invalid_argument{msg.c_str()};
    }

    // Remove the trailing '-'
    links.pop_back();

    return links;
}

std::tuple<std::string, std::tuple<size_t, uint8_t>>
    getFSII2CSearchKeys(const std::string& devPath)
{
    // This combines the FSI and i2C search keys

    auto links = getFSISearchKeys(devPath);
    auto busAndAddr = getI2CSearchKeys(devPath);

    return {std::move(links), std::move(busAndAddr)};
}

size_t getSPISearchKeys(const std::string& devPath)
{
    std::smatch match;

    // Look for spi_master/spiX/ where X is the SPI bus/port number
    // Note: This doesn't distinguish between multiple chips on
    // the same port as no need for it yet.
    std::regex regex{"spi_master/spi(\\d+)/"};

    regex_search(devPath, match, regex);

    if (match.size() != 2)
    {
        std::string msg = "Could not get SPI bus from " + devPath;
        throw std::invalid_argument{msg.c_str()};
    }

    size_t port = std::stoul(match[1].str());

    return port;
}

std::tuple<std::string, size_t> getFSISPISearchKeys(const std::string& devPath)
{

    // Combine the FSI and SPI search keys.
    auto links = getFSISearchKeys(devPath);
    auto bus = getSPISearchKeys(devPath);

    return {std::move(links), std::move(bus)};
}

/**
 * @brief Pull the callouts out of the JSON callout array passed in
 *
 * Create a vector of Callout objects based on the JSON.
 *
 * This will also fill in the 'debug' member on the first callout
 * in the list, which could contain things like the I2C address and
 * bus extracted from the device path.
 *
 * The callouts are in the order they should be added to the PEL.
 *
 * @param[in] calloutJSON - The Callouts JSON array to extract from
 * @param[in] debug - The debug message to add to the first callout
 *
 * @return std::vector<Callout> - The Callout objects
 */
std::vector<Callout> extractCallouts(const nlohmann::json& calloutJSON,
                                     const std::string& debug)
{
    std::vector<Callout> callouts;
    bool addDebug = true;

    // The JSON element passed in is the array of callouts
    if (!calloutJSON.is_array())
    {
        throw std::runtime_error(
            "Dev path callout JSON entry doesn't contain a 'Callouts' array");
    }

    for (auto& callout : calloutJSON)
    {
        Callout c;

        // Add any debug data to the first callout
        if (addDebug && !debug.empty())
        {
            addDebug = false;
            c.debug = debug;
        }

        try
        {
            c.locationCode = callout.at("LocationCode").get<std::string>();
            c.name = callout.at("Name").get<std::string>();
            c.priority = callout.at("Priority").get<std::string>();

            if (callout.contains("MRU"))
            {
                c.mru = callout.at("MRU").get<std::string>();
            }
        }
        catch (const nlohmann::json::out_of_range& e)
        {
            std::string msg =
                "Callout entry missing either LocationCode, Name, or Priority "
                "properties: " +
                callout.dump();
            throw std::runtime_error(msg.c_str());
        }

        callouts.push_back(c);
    }

    return callouts;
}

/**
 * @brief Looks up the callouts in the JSON using the I2C keys.
 *
 * @param[in] i2cBus - The I2C bus
 * @param[in] i2cAddress - The I2C address
 * @param[in] calloutJSON - The JSON containing the callouts
 *
 * @return std::vector<Callout> - The callouts
 */
std::vector<device_callouts::Callout>
    calloutI2C(size_t i2cBus, uint8_t i2cAddress,
               const nlohmann::json& calloutJSON)
{
    auto busString = std::to_string(i2cBus);
    auto addrString = std::to_string(i2cAddress);

    try
    {
        const auto& callouts =
            calloutJSON.at("I2C").at(busString).at(addrString).at("Callouts");

        auto dest = calloutJSON.at("I2C")
                        .at(busString)
                        .at(addrString)
                        .at("Dest")
                        .get<std::string>();

        std::string msg = "I2C: bus: " + busString + " address: " + addrString +
                          " dest: " + dest;

        return extractCallouts(callouts, msg);
    }
    catch (const nlohmann::json::out_of_range& e)
    {
        std::string msg = "Problem looking up I2C callouts on " + busString +
                          " " + addrString + ": " + std::string{e.what()};
        throw std::invalid_argument(msg.c_str());
    }
}

/**
 * @brief Looks up the callouts in the JSON for this I2C path.
 *
 * @param[in] devPath - The device path
 * @param[in] calloutJSON - The JSON containing the callouts
 *
 * @return std::vector<Callout> - The callouts
 */
std::vector<device_callouts::Callout>
    calloutI2CUsingPath(const std::string& devPath,
                        const nlohmann::json& calloutJSON)
{
    auto [bus, address] = getI2CSearchKeys(devPath);

    return calloutI2C(bus, address, calloutJSON);
}

/**
 * @brief Looks up the callouts in the JSON for this FSI path.
 *
 * @param[in] devPath - The device path
 * @param[in] calloutJSON - The JSON containing the callouts
 *
 * @return std::vector<Callout> - The callouts
 */
std::vector<device_callouts::Callout>
    calloutFSI(const std::string& devPath, const nlohmann::json& calloutJSON)
{
    auto links = getFSISearchKeys(devPath);

    try
    {
        const auto& callouts = calloutJSON.at("FSI").at(links).at("Callouts");

        auto dest =
            calloutJSON.at("FSI").at(links).at("Dest").get<std::string>();

        std::string msg = "FSI: links: " + links + " dest: " + dest;

        return extractCallouts(callouts, msg);
    }
    catch (const nlohmann::json::out_of_range& e)
    {
        std::string msg = "Problem looking up FSI callouts on " + links + ": " +
                          std::string{e.what()};
        throw std::invalid_argument(msg.c_str());
    }
}

/**
 * @brief Looks up the callouts in the JSON for this FSI-I2C path.
 *
 * @param[in] devPath - The device path
 * @param[in] calloutJSON - The JSON containing the callouts
 *
 * @return std::vector<Callout> - The callouts
 */
std::vector<device_callouts::Callout>
    calloutFSII2C(const std::string& devPath, const nlohmann::json& calloutJSON)
{
    auto linksAndI2C = getFSII2CSearchKeys(devPath);
    auto links = std::get<std::string>(linksAndI2C);
    const auto& busAndAddr = std::get<1>(linksAndI2C);

    auto busString = std::to_string(std::get<size_t>(busAndAddr));
    auto addrString = std::to_string(std::get<uint8_t>(busAndAddr));

    try
    {
        auto& callouts = calloutJSON.at("FSI-I2C")
                             .at(links)
                             .at(busString)
                             .at(addrString)
                             .at("Callouts");

        auto dest = calloutJSON.at("FSI-I2C")
                        .at(links)
                        .at(busString)
                        .at(addrString)
                        .at("Dest")
                        .get<std::string>();

        std::string msg = "FSI-I2C: links: " + links + " bus: " + busString +
                          " addr: " + addrString + " dest: " + dest;

        return extractCallouts(callouts, msg);
    }
    catch (const nlohmann::json::out_of_range& e)
    {
        std::string msg = "Problem looking up FSI-I2C callouts on " + links +
                          " " + busString + " " + addrString + ": " + e.what();
        throw std::invalid_argument(msg.c_str());
    }
}

/**
 * @brief Looks up the callouts in the JSON for this FSI-SPI path.
 *
 * @param[in] devPath - The device path
 * @param[in] calloutJSON - The JSON containing the callouts
 *
 * @return std::vector<Callout> - The callouts
 */
std::vector<device_callouts::Callout>
    calloutFSISPI(const std::string& devPath, const nlohmann::json& calloutJSON)
{
    auto linksAndSPI = getFSISPISearchKeys(devPath);
    auto links = std::get<std::string>(linksAndSPI);
    auto busString = std::to_string(std::get<size_t>(linksAndSPI));

    try
    {
        auto& callouts =
            calloutJSON.at("FSI-SPI").at(links).at(busString).at("Callouts");

        auto dest = calloutJSON.at("FSI-SPI")
                        .at(links)
                        .at(busString)
                        .at("Dest")
                        .get<std::string>();

        std::string msg = "FSI-SPI: links: " + links + " bus: " + busString +
                          " dest: " + dest;

        return extractCallouts(callouts, msg);
    }
    catch (const nlohmann::json::out_of_range& e)
    {
        std::string msg = "Problem looking up FSI-SPI callouts on " + links +
                          " " + busString + ": " + std::string{e.what()};
        throw std::invalid_argument(msg.c_str());
    }
}

/**
 * @brief Returns the callouts from the JSON based on the input
 *        device path.
 *
 * @param[in] devPath - The device path
 * @param[in] json - The callout JSON
 *
 * @return std::vector<Callout> - The list of callouts
 */
std::vector<device_callouts::Callout> findCallouts(const std::string& devPath,
                                                   const nlohmann::json& json)
{
    std::vector<Callout> callouts;
    fs::path path;

    // Gives the /sys/devices/platform/ path
    try
    {
        path = fs::canonical(devPath);
    }
    catch (const fs::filesystem_error& e)
    {
        // Path not there, still try to do the callout
        path = devPath;
    }

    switch (util::getCalloutType(path))
    {
        case util::CalloutType::i2c:
            callouts = calloutI2CUsingPath(path, json);
            break;
        case util::CalloutType::fsi:
            callouts = calloutFSI(path, json);
            break;
        case util::CalloutType::fsii2c:
            callouts = calloutFSII2C(path, json);
            break;
        case util::CalloutType::fsispi:
            callouts = calloutFSISPI(path, json);
            break;
        default:
            std::string msg =
                "Could not get callout type from device path: " + path.string();
            throw std::invalid_argument{msg.c_str()};
            break;
    }

    return callouts;
}

CalloutType getCalloutType(const std::string& devPath)
{
    if ((devPath.find("fsi-master") != std::string::npos) &&
        (devPath.find("i2c-") != std::string::npos))
    {
        return CalloutType::fsii2c;
    }

    if ((devPath.find("fsi-master") != std::string::npos) &&
        (devPath.find("spi") != std::string::npos))
    {
        return CalloutType::fsispi;
    }

    // Treat anything else FSI related as plain FSI
    if (devPath.find("fsi-master") != std::string::npos)
    {
        return CalloutType::fsi;
    }

    if (devPath.find("i2c-bus/i2c-") != std::string::npos)
    {
        return CalloutType::i2c;
    }

    return CalloutType::unknown;
}

} // namespace util

std::vector<Callout> getCallouts(const std::string& devPath,
                                 const std::vector<std::string>& compatibleList)
{
    auto json = util::loadJSON(compatibleList);
    return util::findCallouts(devPath, json);
}

std::vector<Callout>
    getI2CCallouts(size_t i2cBus, uint8_t i2cAddress,
                   const std::vector<std::string>& compatibleList)
{
    auto json = util::loadJSON(compatibleList);
    return util::calloutI2C(i2cBus, i2cAddress, json);
}

} // namespace openpower::pels::device_callouts
