/**
 * 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 <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}};

JsonConfig::JsonConfig(sdbusplus::bus::bus& bus) : _bus(bus)
{
    using config = fan::JsonConfig;

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

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(_bus, confAppName, confFileName)));

        for (auto& p : _policies)
        {
            p->monitor();
        }
        log<level::INFO>("Configuration loaded successfully");
    }
    catch (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>();
        }

        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());
        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)
{
    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);
    }
    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>();

    return std::make_unique<PolicyAccess<Gpio, JsonConfig>>(fanIndex, physpath,
                                                            devpath, key);
}

} // 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::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);
}

// Get a `Fallback` redundancy policy for the fan
std::unique_ptr<RedundancyPolicy> getFallback(const fanPolicy& fan)
{
    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);
}

} // namespace rpolicy

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