/**
 * 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.
 */
#pragma once

#include "sdbusplus.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <sdeventplus/source/signal.hpp>

#include <filesystem>
#include <format>
#include <fstream>

namespace phosphor::fan
{

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

constexpr auto confOverridePath = "/etc/phosphor-fan-presence";
constexpr auto confBasePath = "/usr/share/phosphor-fan-presence";
constexpr auto confCompatServ = "xyz.openbmc_project.EntityManager";
constexpr auto confCompatIntf =
    "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
constexpr auto confCompatProp = "Names";

/**
 * @class NoConfigFound - A no JSON configuration found exception
 *
 * A no JSON configuration found exception that is used to denote that a JSON
 * configuration has not been found yet.
 */
class NoConfigFound : public std::runtime_error
{
  public:
    NoConfigFound() = delete;
    NoConfigFound(const NoConfigFound&) = delete;
    NoConfigFound(NoConfigFound&&) = delete;
    NoConfigFound& operator=(const NoConfigFound&) = delete;
    NoConfigFound& operator=(NoConfigFound&&) = delete;
    ~NoConfigFound() = default;

    /**
     * @brief No JSON configuration found exception object
     *
     * When attempting to find the JSON configuration file(s), a NoConfigFound
     * exception can be thrown to denote that at that time finding/loading the
     * JSON configuration file(s) for a fan application failed. Details on what
     * application and JSON configuration file that failed to be found will be
     * logged resulting in the application being terminated.
     *
     * @param[in] details - Additional details
     */
    NoConfigFound(const std::string& appName, const std::string& fileName) :
        std::runtime_error(std::format("JSON configuration not found [Could "
                                       "not find fan {} conf file {}]",
                                       appName, fileName)
                               .c_str())
    {}
};

class JsonConfig
{
  public:
    /**
     * @brief Get the object paths with the compatible interface
     *
     * Retrieve all the object paths implementing the compatible interface for
     * configuration file loading.
     */
    static auto& getCompatObjPaths() __attribute__((pure))
    {
        static auto paths = util::SDBusPlus::getSubTreePathsRaw(
            util::SDBusPlus::getBus(), "/", confCompatIntf, 0);
        return paths;
    }

    /**
     * @brief Constructor
     *
     * Attempts to set the list of compatible values from the compatible
     * interface and call the fan app's function to load its config file(s). If
     * the compatible interface is not found, it subscribes to the
     * interfacesAdded signal for that interface on the compatible service
     * defined above.
     *
     * @param[in] func - Fan app function to call to load its config file(s)
     */
    JsonConfig(std::function<void()> func) : _loadFunc(func)
    {
        std::vector<std::string> compatObjPaths;

        _match = std::make_unique<sdbusplus::bus::match_t>(
            util::SDBusPlus::getBus(),
            sdbusplus::bus::match::rules::interfacesAdded() +
                sdbusplus::bus::match::rules::sender(confCompatServ),
            std::bind(&JsonConfig::compatIntfAdded, this,
                      std::placeholders::_1));

        try
        {
            compatObjPaths = getCompatObjPaths();
        }
        catch (const util::DBusMethodError&)
        {
            // Compatible interface does not exist on any dbus object yet
        }

        if (!compatObjPaths.empty())
        {
            for (auto& path : compatObjPaths)
            {
                try
                {
                    // Retrieve json config compatible relative path
                    // locations (last one found will be what's used if more
                    // than one dbus object implementing the comptaible
                    // interface exists).
                    _confCompatValues =
                        util::SDBusPlus::getProperty<std::vector<std::string>>(
                            util::SDBusPlus::getBus(), path, confCompatIntf,
                            confCompatProp);
                }
                catch (const util::DBusError&)
                {
                    // Compatible property unavailable on this dbus object
                    // path's compatible interface, ignore
                }
            }
            _loadFunc();
        }
        else
        {
            // Check if required config(s) are found not needing the
            // compatible interface, otherwise this is intended to catch the
            // exception thrown by the getConfFile function when the
            // required config file was not found. This would then result in
            // waiting for the compatible interfacesAdded signal
            try
            {
                _loadFunc();
            }
            catch (const NoConfigFound&)
            {
                // Wait for compatible interfacesAdded signal
            }
        }
    }

    /**
     * @brief InterfacesAdded callback function for the compatible interface.
     *
     * @param[in] msg - The D-Bus message contents
     *
     * If the compatible interface is found, it uses the compatible property on
     * the interface to set the list of compatible values to be used when
     * attempting to get a configuration file. Once the list of compatible
     * values has been updated, it calls the load function.
     */
    void compatIntfAdded(sdbusplus::message_t& msg)
    {
        sdbusplus::message::object_path op;
        std::map<std::string,
                 std::map<std::string, std::variant<std::vector<std::string>>>>
            intfProps;

        msg.read(op, intfProps);

        if (intfProps.find(confCompatIntf) == intfProps.end())
        {
            return;
        }

        const auto& props = intfProps.at(confCompatIntf);
        // Only one dbus object with the compatible interface is used at a time
        _confCompatValues =
            std::get<std::vector<std::string>>(props.at(confCompatProp));
        _loadFunc();
    }

    /**
     * Get the json configuration file. The first location found to contain
     * the json config file for the given fan application is used from the
     * following locations in order.
     * 1.) From the confOverridePath location
     * 2.) From the default confBasePath location
     * 3.) From config file found using an entry from a list obtained from an
     * interface's property as a relative path extension on the base path where:
     *     interface = Interface set in confCompatIntf with the property
     *     property = Property set in confCompatProp containing a list of
     *                subdirectories in priority order to find a config
     *
     * @brief Get the configuration file to be used
     *
     * @param[in] appName - The phosphor-fan-presence application name
     * @param[in] fileName - Application's configuration file's name
     * @param[in] isOptional - Config file is optional, default to 'false'
     *
     * @return filesystem path
     *     The filesystem path to the configuration file to use
     */
    static const fs::path getConfFile(const std::string& appName,
                                      const std::string& fileName,
                                      bool isOptional = false)
    {
        // Check override location
        fs::path confFile = fs::path{confOverridePath} / appName / fileName;
        if (fs::exists(confFile))
        {
            return confFile;
        }

        // If the default file is there, use it
        confFile = fs::path{confBasePath} / appName / fileName;
        if (fs::exists(confFile))
        {
            return confFile;
        }

        // Look for a config file at each entry relative to the base
        // path and use the first one found
        auto it =
            std::find_if(_confCompatValues.begin(), _confCompatValues.end(),
                         [&confFile, &appName, &fileName](const auto& value) {
            confFile = fs::path{confBasePath} / appName / value / fileName;
            return fs::exists(confFile);
            });
        if (it == _confCompatValues.end())
        {
            confFile.clear();
        }

        if (confFile.empty() && !isOptional)
        {
            throw NoConfigFound(appName, fileName);
        }

        return confFile;
    }

    /**
     * @brief Load the JSON config file
     *
     * @param[in] confFile - File system path of the configuration file to load
     *
     * @return Parsed JSON object
     *     The parsed JSON configuration file object
     */
    static const json load(const fs::path& confFile)
    {
        std::ifstream file;
        json jsonConf;

        if (!confFile.empty() && fs::exists(confFile))
        {
            log<level::INFO>(
                std::format("Loading configuration from {}", confFile.string())
                    .c_str());
            file.open(confFile);
            try
            {
                // Enable ignoring `//` or `/* */` comments
                jsonConf = json::parse(file, nullptr, true, true);
            }
            catch (const std::exception& e)
            {
                log<level::ERR>(
                    std::format(
                        "Failed to parse JSON config file: {}, error: {}",
                        confFile.string(), e.what())
                        .c_str());
                throw std::runtime_error(
                    std::format(
                        "Failed to parse JSON config file: {}, error: {}",
                        confFile.string(), e.what())
                        .c_str());
            }
        }
        else
        {
            log<level::ERR>(std::format("Unable to open JSON config file: {}",
                                        confFile.string())
                                .c_str());
            throw std::runtime_error(
                std::format("Unable to open JSON config file: {}",
                            confFile.string())
                    .c_str());
        }

        return jsonConf;
    }

    /**
     * @brief Return the compatible values property
     *
     * @return const std::vector<std::string>& - The values
     */
    static const std::vector<std::string>& getCompatValues()
    {
        return _confCompatValues;
    }

  private:
    /* Load function to call for a fan app to load its config file(s). */
    std::function<void()> _loadFunc;

    /**
     * @brief The interfacesAdded match that is used to wait
     *        for the IBMCompatibleSystem interface to show up.
     */
    std::unique_ptr<sdbusplus::bus::match_t> _match;

    /**
     * @brief List of compatible values from the compatible interface
     *
     * Only supports a single instance of the compatible interface on a dbus
     * object. If more than one dbus object exists with the compatible
     * interface, the last one found will be the list of compatible values used.
     */
    inline static std::vector<std::string> _confCompatValues;
};

} // namespace phosphor::fan
