/**
 * 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 "manager.hpp"

#include "chassis.hpp"
#include "config_file_parser.hpp"
#include "exception_utils.hpp"
#include "rule.hpp"
#include "utility.hpp"

#include <xyz/openbmc_project/Common/error.hpp>

#include <algorithm>
#include <chrono>
#include <exception>
#include <functional>
#include <map>
#include <tuple>
#include <utility>
#include <variant>

namespace phosphor::power::regulators
{

namespace fs = std::filesystem;

constexpr auto busName = "xyz.openbmc_project.Power.Regulators";
constexpr auto managerObjPath = "/xyz/openbmc_project/power/regulators/manager";
constexpr auto compatibleIntf =
    "xyz.openbmc_project.Configuration.IBMCompatibleSystem";
constexpr auto compatibleNamesProp = "Names";

/**
 * Default configuration file name.  This is used when the system does not
 * implement the D-Bus compatible interface.
 */
constexpr auto defaultConfigFileName = "config.json";

/**
 * Standard configuration file directory.  This directory is part of the
 * firmware install image.  It contains the standard version of the config file.
 */
const fs::path standardConfigFileDir{"/usr/share/phosphor-regulators"};

/**
 * Test configuration file directory.  This directory can contain a test version
 * of the config file.  The test version will override the standard version.
 */
const fs::path testConfigFileDir{"/etc/phosphor-regulators"};

Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) :
    ManagerObject{bus, managerObjPath, true}, bus{bus}, eventLoop{event},
    services{bus}
{
    // Subscribe to D-Bus interfacesAdded signal from Entity Manager.  This
    // notifies us if the compatible interface becomes available later.
    std::string matchStr = sdbusplus::bus::match::rules::interfacesAdded() +
                           sdbusplus::bus::match::rules::sender(
                               "xyz.openbmc_project.EntityManager");
    std::unique_ptr<sdbusplus::server::match::match> matchPtr =
        std::make_unique<sdbusplus::server::match::match>(
            bus, matchStr,
            std::bind(&Manager::interfacesAddedHandler, this,
                      std::placeholders::_1));
    signals.emplace_back(std::move(matchPtr));

    // Try to find compatible system types using D-Bus compatible interface.
    // Note that it might not be supported on this system, or the service that
    // provides the interface might not be running yet.
    findCompatibleSystemTypes();

    // Try to find and load the JSON configuration file
    loadConfigFile();

    // Obtain dbus service name
    bus.request_name(busName);
}

void Manager::configure()
{
    // Clear any cached data or error history related to hardware devices
    clearHardwareData();

    // Verify System object exists; this means config file has been loaded
    if (system)
    {
        // Configure the regulator devices in the system
        system->configure(services);
    }
    else
    {
        // Write error message to journal
        services.getJournal().logError("Unable to configure regulator devices: "
                                       "Configuration file not loaded");

        // TODO: Add code to wait for EntityManager to publish the compatible
        // interface before logging this error.

        // Log critical error since regulators could not be configured.  Could
        // cause hardware damage if default regulator settings are very wrong.
        /*
        services.getErrorLogging().logConfigFileError(Entry::Level::Critical,
                                                      services.getJournal());
        */

        // Throw InternalFailure to propogate error status to D-Bus client
        /*
        throw sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure{};
        */
    }
}

void Manager::interfacesAddedHandler(sdbusplus::message::message& msg)
{
    // Verify message is valid
    if (!msg)
    {
        return;
    }

    try
    {
        // Read object path for object that was created or had interface added
        sdbusplus::message::object_path objPath;
        msg.read(objPath);

        // Read the dictionary whose keys are interface names and whose values
        // are dictionaries containing the interface property names and values
        std::map<std::string,
                 std::map<std::string, std::variant<std::vector<std::string>>>>
            intfProp;
        msg.read(intfProp);

        // Find the compatible interface, if present
        auto itIntf = intfProp.find(compatibleIntf);
        if (itIntf != intfProp.cend())
        {
            // Find the Names property of the compatible interface, if present
            auto itProp = itIntf->second.find(compatibleNamesProp);
            if (itProp != itIntf->second.cend())
            {
                // Get value of Names property
                auto propValue = std::get<0>(itProp->second);
                if (!propValue.empty())
                {
                    // Store list of compatible system types
                    compatibleSystemTypes = propValue;

                    // Find and load JSON config file based on system types
                    loadConfigFile();
                }
            }
        }
    }
    catch (const std::exception&)
    {
        // Error trying to read interfacesAdded message.  One possible cause
        // could be a property whose value is not a std::vector<std::string>.
    }
}

void Manager::monitor(bool enable)
{
    if (enable)
    {
        /* Temporarily comment out until monitoring is supported.
            Timer timer(eventLoop, std::bind(&Manager::timerExpired, this));
            // Set timer as a repeating 1sec timer
            timer.restart(std::chrono::milliseconds(1000));
            timers.emplace_back(std::move(timer));
        */
    }
    else
    {
        /* Temporarily comment out until monitoring is supported.
            // Delete all timers to disable monitoring
            timers.clear();
        */

        // Verify System object exists; this means config file has been loaded
        if (system)
        {
            // Close the regulator devices in the system.  Monitoring is
            // normally disabled because the system is being powered off.  The
            // devices should be closed in case hardware is removed or replaced
            // while the system is powered off.
            system->closeDevices(services);
        }
    }
}

void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
                            const struct signalfd_siginfo* /*sigInfo*/)
{
    // Reload the JSON configuration file
    loadConfigFile();
}

void Manager::timerExpired()
{
    // TODO Analyze, refresh sensor status, and
    // collect/update telemetry for each regulator
}

void Manager::clearHardwareData()
{
    // Clear any cached hardware presence data and VPD values
    services.getPresenceService().clearCache();
    services.getVPD().clearCache();

    // Verify System object exists; this means config file has been loaded
    if (system)
    {
        // Clear any cached hardware data in the System object
        system->clearCache();
    }

    // TODO: Clear error history related to hardware devices
}

void Manager::findCompatibleSystemTypes()
{
    using namespace phosphor::power::util;

    try
    {
        // Query object mapper for object paths that implement the compatible
        // interface.  Returns a map of object paths to a map of services names
        // to their interfaces.
        DbusSubtree subTree = getSubTree(bus, "/xyz/openbmc_project/inventory",
                                         compatibleIntf, 0);

        // Get the first object path
        auto objectIt = subTree.cbegin();
        if (objectIt != subTree.cend())
        {
            std::string objPath = objectIt->first;

            // Get the first service name
            auto serviceIt = objectIt->second.cbegin();
            if (serviceIt != objectIt->second.cend())
            {
                std::string service = serviceIt->first;
                if (!service.empty())
                {
                    // Get compatible system types property value
                    getProperty(compatibleIntf, compatibleNamesProp, objPath,
                                service, bus, compatibleSystemTypes);
                }
            }
        }
    }
    catch (const std::exception&)
    {
        // Compatible system types information is not available.  The current
        // system might not support the interface, or the service that
        // implements the interface might not be running yet.
    }
}

fs::path Manager::findConfigFile()
{
    // Build list of possible base file names
    std::vector<std::string> fileNames{};

    // Add possible file names based on compatible system types (if any)
    for (const std::string& systemType : compatibleSystemTypes)
    {
        // Replace all spaces and commas in system type name with underscores
        std::string fileName{systemType};
        std::replace(fileName.begin(), fileName.end(), ' ', '_');
        std::replace(fileName.begin(), fileName.end(), ',', '_');

        // Append .json suffix and add to list
        fileName.append(".json");
        fileNames.emplace_back(fileName);
    }

    // Add default file name for systems that don't use compatible interface
    fileNames.emplace_back(defaultConfigFileName);

    // Look for a config file with one of the possible base names
    for (const std::string& fileName : fileNames)
    {
        // Check if file exists in test directory
        fs::path pathName{testConfigFileDir / fileName};
        if (fs::exists(pathName))
        {
            return pathName;
        }

        // Check if file exists in standard directory
        pathName = standardConfigFileDir / fileName;
        if (fs::exists(pathName))
        {
            return pathName;
        }
    }

    // No config file found; return empty path
    return fs::path{};
}

void Manager::loadConfigFile()
{
    try
    {
        // Find the absolute path to the config file
        fs::path pathName = findConfigFile();
        if (!pathName.empty())
        {
            // Log info message in journal; config file path is important
            services.getJournal().logInfo("Loading configuration file " +
                                          pathName.string());

            // Parse the config file
            std::vector<std::unique_ptr<Rule>> rules{};
            std::vector<std::unique_ptr<Chassis>> chassis{};
            std::tie(rules, chassis) = config_file_parser::parse(pathName);

            // Store config file information in a new System object.  The old
            // System object, if any, is automatically deleted.
            system =
                std::make_unique<System>(std::move(rules), std::move(chassis));
        }
    }
    catch (const std::exception& e)
    {
        // Log error messages in journal
        services.getJournal().logError(exception_utils::getMessages(e));
        services.getJournal().logError("Unable to load configuration file");

        // Log error
        services.getErrorLogging().logConfigFileError(Entry::Level::Error,
                                                      services.getJournal());
    }
}

} // namespace phosphor::power::regulators
