/**
 * 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 <sdbusplus/bus.hpp>

#include <chrono>
#include <exception>
#include <stdexcept>
#include <tuple>
#include <utility>
#include <variant>

namespace phosphor::power::regulators
{

namespace fs = std::filesystem;

/**
 * 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, objPath, true}, bus{bus}, eventLoop{event}, services{bus}
{
    /* Temporarily comment out until D-Bus interface is defined and available.
        // Subscribe to interfacesAdded signal for filename property
        std::unique_ptr<sdbusplus::server::match::match> matchPtr =
            std::make_unique<sdbusplus::server::match::match>(
                bus,
                sdbusplus::bus::match::rules::interfacesAdded(sysDbusObj).c_str(),
                std::bind(std::mem_fn(&Manager::signalHandler), this,
                          std::placeholders::_1));
        signals.emplace_back(std::move(matchPtr));

        // Attempt to get the filename property from dbus
        setFileName(getFileNameDbus());
    */

    // Temporarily hard-code JSON config file name to first system that will use
    // this application.  Remove this when D-Bus interface is available.
    fileName = "ibm_rainier.json";

    if (!fileName.empty())
    {
        loadConfigFile();
    }

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

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

    // TODO Configuration errors that should halt poweron,
    // throw InternalFailure exception (or similar) to
    // fail the call(busctl) to this method
}

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 at standby.
            system->closeDevices();
        }
    }
}

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

void Manager::sighupHandler(sdeventplus::source::Signal& /*sigSrc*/,
                            const struct signalfd_siginfo* /*sigInfo*/)
{
    if (!fileName.empty())
    {
        loadConfigFile();
    }
}

void Manager::signalHandler(sdbusplus::message::message& msg)
{
    if (msg)
    {
        sdbusplus::message::object_path op;
        msg.read(op);
        if (static_cast<const std::string&>(op) != sysDbusPath)
        {
            // Object path does not match the path
            return;
        }

        // An interfacesAdded signal returns a dictionary of interface
        // names to a dictionary of properties and their values
        // https://dbus.freedesktop.org/doc/dbus-specification.html
        std::map<std::string, std::map<std::string, std::variant<std::string>>>
            intfProp;
        msg.read(intfProp);
        auto itIntf = intfProp.find(sysDbusIntf);
        if (itIntf == intfProp.cend())
        {
            // Interface not found on the path
            return;
        }
        auto itProp = itIntf->second.find(sysDbusProp);
        if (itProp == itIntf->second.cend())
        {
            // Property not found on the interface
            return;
        }
        // Set fileName and call parse json function
        setFileName(std::get<std::string>(itProp->second));
        if (!fileName.empty())
        {
            loadConfigFile();
        }
    }
}

const std::string Manager::getFileNameDbus()
{
    std::string fileName = "";
    using namespace phosphor::power::util;

    try
    {
        // Do not log an error when service or property are not found
        auto service = getService(sysDbusPath, sysDbusIntf, bus, false);
        if (!service.empty())
        {
            getProperty(sysDbusIntf, sysDbusProp, sysDbusPath, service, bus,
                        fileName);
        }
    }
    catch (const sdbusplus::exception::SdBusError&)
    {
        // File name property not available on dbus
        fileName = "";
    }

    return fileName;
}

fs::path Manager::findConfigFile()
{
    // First look in the test directory
    fs::path pathName{testConfigFileDir / fileName};
    if (!fs::exists(pathName))
    {
        // Look in the standard directory
        pathName = standardConfigFileDir / fileName;
        if (!fs::exists(pathName))
        {
            throw std::runtime_error{"Configuration file does not exist: " +
                                     pathName.string()};
        }
    }

    return pathName;
}

void Manager::loadConfigFile()
{
    try
    {
        // Find the absolute path to the config file
        fs::path pathName = findConfigFile();

        // 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");

        // TODO: Create error log entry
    }
}

} // namespace phosphor::power::regulators
