/**
 * 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 "journal.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}
{
    /* 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()
{
    // 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)
    {
        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
    {
        // Delete all timers to disable monitoring
        timers.clear();
    }
}

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
        journal::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
        exception_utils::log(e);
        journal::logErr("Unable to load configuration file");

        // TODO: Create error log entry
    }
}

} // namespace phosphor::power::regulators
