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