/**
 * Copyright © 2019 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 "json_parser.hpp"

#include "anyof.hpp"
#include "fallback.hpp"
#include "gpio.hpp"
#include "json_config.hpp"
#include "sdbusplus.hpp"
#include "tach.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Logging/Create/server.hpp>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>

#include <filesystem>
#include <fstream>
#include <string>

namespace phosphor
{
namespace fan
{
namespace presence
{

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

policies JsonConfig::_policies;
const std::map<std::string, methodHandler> JsonConfig::_methods = {
    {"tach", method::getTach}, {"gpio", method::getGpio}};
const std::map<std::string, rpolicyHandler> JsonConfig::_rpolicies = {
    {"anyof", rpolicy::getAnyof}, {"fallback", rpolicy::getFallback}};

const auto loggingPath = "/xyz/openbmc_project/logging";
const auto loggingCreateIface = "xyz.openbmc_project.Logging.Create";

JsonConfig::JsonConfig(sdbusplus::bus_t& bus) : _bus(bus) {}

void JsonConfig::start()
{
    using config = fan::JsonConfig;

    if (!_loaded)
    {
        process(config::load(config::getConfFile(confAppName, confFileName)));

        _loaded = true;

        for (auto& p : _policies)
        {
            p->monitor();
        }
    }
}

const policies& JsonConfig::get()
{
    return _policies;
}

void JsonConfig::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
                               const struct signalfd_siginfo* /*sigInfo*/)
{
    try
    {
        using config = fan::JsonConfig;

        _reporter.reset();

        // Load and process the json configuration
        process(config::load(config::getConfFile(confAppName, confFileName)));

        for (auto& p : _policies)
        {
            p->monitor();
        }
        log<level::INFO>("Configuration loaded successfully");
    }
    catch (const std::runtime_error& re)
    {
        log<level::ERR>("Error loading config, no config changes made",
                        entry("LOAD_ERROR=%s", re.what()));
    }
}

void JsonConfig::process(const json& jsonConf)
{
    policies policies;
    std::vector<fanPolicy> fans;
    // Set the expected number of fan entries
    // to be size of the list of fan json config entries
    // (Must be done to eliminate vector reallocation of fan references)
    fans.reserve(jsonConf.size());
    for (auto& member : jsonConf)
    {
        if (!member.contains("name") || !member.contains("path") ||
            !member.contains("methods") || !member.contains("rpolicy"))
        {
            log<level::ERR>("Missing required fan presence properties",
                            entry("REQUIRED_PROPERTIES=%s",
                                  "{name, path, methods, rpolicy}"));
            throw std::runtime_error(
                "Missing required fan presence properties");
        }

        // Loop thru the configured methods of presence detection
        std::vector<std::unique_ptr<PresenceSensor>> sensors;
        for (auto& method : member["methods"].items())
        {
            if (!method.value().contains("type"))
            {
                log<level::ERR>(
                    "Missing required fan presence method type",
                    entry("FAN_NAME=%s",
                          member["name"].get<std::string>().c_str()));
                throw std::runtime_error(
                    "Missing required fan presence method type");
            }
            // The method type of fan presence detection
            // (Must have a supported function within the method namespace)
            auto type = method.value()["type"].get<std::string>();
            std::transform(type.begin(), type.end(), type.begin(), tolower);
            auto func = _methods.find(type);
            if (func != _methods.end())
            {
                // Call function for method type
                auto sensor = func->second(fans.size(), method.value());
                if (sensor)
                {
                    sensors.emplace_back(std::move(sensor));
                }
            }
            else
            {
                log<level::ERR>(
                    "Invalid fan presence method type",
                    entry("FAN_NAME=%s",
                          member["name"].get<std::string>().c_str()),
                    entry("METHOD_TYPE=%s", type.c_str()));
                throw std::runtime_error("Invalid fan presence method type");
            }
        }

        // Get the amount of time a fan must be not present before
        // creating an error.
        std::optional<size_t> timeUntilError;
        if (member.contains("fan_missing_error_time"))
        {
            timeUntilError = member["fan_missing_error_time"].get<size_t>();
        }

        std::unique_ptr<EEPROMDevice> eepromDevice;
        if (member.contains("eeprom"))
        {
            const auto& eeprom = member.at("eeprom");
            if (!eeprom.contains("bus_address") ||
                !eeprom.contains("driver_name") ||
                !eeprom.contains("bind_delay_ms"))
            {
                log<level::ERR>(
                    "Missing address, driver_name, or bind_delay_ms in eeprom "
                    "section",
                    entry("FAN_NAME=%s",
                          member["name"].get<std::string>().c_str()));

                throw std::runtime_error("Missing address, driver_name, or "
                                         "bind_delay_ms in eeprom section");
            }
            eepromDevice = std::make_unique<EEPROMDevice>(
                eeprom["bus_address"].get<std::string>(),
                eeprom["driver_name"].get<std::string>(),
                eeprom["bind_delay_ms"].get<size_t>());
        }

        auto fan = std::make_tuple(member["name"], member["path"],
                                   timeUntilError);
        // Create a fan object
        fans.emplace_back(std::make_tuple(fan, std::move(sensors)));

        // Add fan presence policy
        auto policy = getPolicy(member["rpolicy"], fans.back(),
                                std::move(eepromDevice));
        if (policy)
        {
            policies.emplace_back(std::move(policy));
        }
    }

    // Success, refresh fans and policies lists
    _fans.clear();
    _fans.swap(fans);

    _policies.clear();
    _policies.swap(policies);

    // Create the error reporter class if necessary
    if (std::any_of(_fans.begin(), _fans.end(), [](const auto& fan) {
        return std::get<std::optional<size_t>>(std::get<Fan>(fan)) !=
               std::nullopt;
    }))
    {
        _reporter = std::make_unique<ErrorReporter>(_bus, _fans);
    }
}

std::unique_ptr<RedundancyPolicy>
    JsonConfig::getPolicy(const json& rpolicy, const fanPolicy& fpolicy,
                          std::unique_ptr<EEPROMDevice> eepromDevice)
{
    if (!rpolicy.contains("type"))
    {
        log<level::ERR>(
            "Missing required fan presence policy type",
            entry("FAN_NAME=%s",
                  std::get<fanPolicyFanPos>(std::get<Fan>(fpolicy)).c_str()),
            entry("REQUIRED_PROPERTIES=%s", "{type}"));
        throw std::runtime_error("Missing required fan presence policy type");
    }

    // The redundancy policy type for fan presence detection
    // (Must have a supported function within the rpolicy namespace)
    auto type = rpolicy["type"].get<std::string>();
    std::transform(type.begin(), type.end(), type.begin(), tolower);
    auto func = _rpolicies.find(type);
    if (func != _rpolicies.end())
    {
        // Call function for redundancy policy type and return the policy
        return func->second(fpolicy, std::move(eepromDevice));
    }
    else
    {
        log<level::ERR>(
            "Invalid fan presence policy type",
            entry("FAN_NAME=%s",
                  std::get<fanPolicyFanPos>(std::get<Fan>(fpolicy)).c_str()),
            entry("RPOLICY_TYPE=%s", type.c_str()));
        throw std::runtime_error("Invalid fan presence methods policy type");
    }
}

/**
 * Methods of fan presence detection function definitions
 */
namespace method
{
// Get a constructed presence sensor for fan presence detection by tach
std::unique_ptr<PresenceSensor> getTach(size_t fanIndex, const json& method)
{
    if (!method.contains("sensors") || method["sensors"].size() == 0)
    {
        log<level::ERR>("Missing required tach method properties",
                        entry("FAN_ENTRY=%d", fanIndex),
                        entry("REQUIRED_PROPERTIES=%s", "{sensors}"));
        throw std::runtime_error("Missing required tach method properties");
    }

    std::vector<std::string> sensors;
    for (auto& sensor : method["sensors"])
    {
        sensors.emplace_back(sensor.get<std::string>());
    }

    return std::make_unique<PolicyAccess<Tach, JsonConfig>>(fanIndex,
                                                            std::move(sensors));
}

// Get a constructed presence sensor for fan presence detection by gpio
std::unique_ptr<PresenceSensor> getGpio(size_t fanIndex, const json& method)
{
    if (!method.contains("physpath") || !method.contains("devpath") ||
        !method.contains("key"))
    {
        log<level::ERR>(
            "Missing required gpio method properties",
            entry("FAN_ENTRY=%d", fanIndex),
            entry("REQUIRED_PROPERTIES=%s", "{physpath, devpath, key}"));
        throw std::runtime_error("Missing required gpio method properties");
    }

    auto physpath = method["physpath"].get<std::string>();
    auto devpath = method["devpath"].get<std::string>();
    auto key = method["key"].get<unsigned int>();

    try
    {
        return std::make_unique<PolicyAccess<Gpio, JsonConfig>>(
            fanIndex, physpath, devpath, key);
    }
    catch (const sdbusplus::exception_t& e)
    {
        namespace sdlogging = sdbusplus::xyz::openbmc_project::Logging::server;

        log<level::ERR>(
            std::format(
                "Error creating Gpio device bridge, hardware not detected: {}",
                e.what())
                .c_str());

        auto severity =
            sdlogging::convertForMessage(sdlogging::Entry::Level::Error);

        std::map<std::string, std::string> additionalData{
            {"PHYSPATH", physpath},
            {"DEVPATH", devpath},
            {"FANINDEX", std::to_string(fanIndex)}};

        try
        {
            util::SDBusPlus::lookupAndCallMethod(
                loggingPath, loggingCreateIface, "Create",
                "xyz.openbmc_project.Fan.Presence.Error.GPIODeviceUnavailable",
                severity, additionalData);
        }
        catch (const util::DBusError& e)
        {
            log<level::ERR>(std::format("Call to create an error log for "
                                        "presence-sensor failure failed: {}",
                                        e.what())
                                .c_str());
        }

        return std::make_unique<PolicyAccess<NullGpio, JsonConfig>>();
    }
}

} // namespace method

/**
 * Redundancy policies for fan presence detection function definitions
 */
namespace rpolicy
{
// Get an `Anyof` redundancy policy for the fan
std::unique_ptr<RedundancyPolicy>
    getAnyof(const fanPolicy& fan, std::unique_ptr<EEPROMDevice> eepromDevice)
{
    std::vector<std::reference_wrapper<PresenceSensor>> pSensors;
    for (auto& fanSensor : std::get<fanPolicySensorListPos>(fan))
    {
        pSensors.emplace_back(*fanSensor);
    }

    return std::make_unique<AnyOf>(std::get<fanPolicyFanPos>(fan), pSensors,
                                   std::move(eepromDevice));
}

// Get a `Fallback` redundancy policy for the fan
std::unique_ptr<RedundancyPolicy>
    getFallback(const fanPolicy& fan,
                std::unique_ptr<EEPROMDevice> eepromDevice)
{
    std::vector<std::reference_wrapper<PresenceSensor>> pSensors;
    for (auto& fanSensor : std::get<fanPolicySensorListPos>(fan))
    {
        // Place in the order given to fallback correctly
        pSensors.emplace_back(*fanSensor);
    }

    return std::make_unique<Fallback>(std::get<fanPolicyFanPos>(fan), pSensors,
                                      std::move(eepromDevice));
}

} // namespace rpolicy

} // namespace presence
} // namespace fan
} // namespace phosphor
