#include "config.h"

#include "fw_update_watch.hpp"

#include "common_utils.hpp"
#include "create_pel.hpp"
#include "pdbg_utils.hpp"

#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <sdbusplus/exception.hpp>

#include <filesystem>
#include <format>

namespace openpower
{
namespace phal
{
namespace fwupdate
{
using namespace phosphor::logging;
namespace fs = std::filesystem;

using Message = std::string;
using Attributes = std::variant<Message>;
using PropertyName = std::string;
using PropertyMap = std::map<PropertyName, Attributes>;
using InterfaceName = std::string;
using InterfaceMap = std::map<InterfaceName, PropertyMap>;

void Watch::fwIntfAddedCallback(sdbusplus::message_t& msg)
{
    //  DBusInterfaceAdded interfaces;
    sdbusplus::message::object_path objectPath;
    InterfaceMap interfaceMap;

    try
    {
        msg.read(objectPath, interfaceMap);
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>(std::format("Failed to parse software add signal"
                                    "Exception [{}] REPLY_SIG [{}]",
                                    e.what(), msg.get_signature())
                            .c_str());
        return;
    }

    auto iter = interfaceMap.find("xyz.openbmc_project.Software.Activation");
    if (iter == interfaceMap.end())
    {
        // Skip not related Software Activation
        return;
    }

    auto attr = iter->second.find("Activation");
    if (attr == iter->second.end())
    {
        // Skip not related to Activation property.
        return;
    }

    auto& imageProperty = std::get<InterfaceName>(attr->second);
    if (imageProperty.empty())
    {
        // Skip, no image property
        return;
    }

    if (imageProperty ==
            "xyz.openbmc_project.Software.Activation.Activations.Ready" &&
        !isSoftwareUpdateInProgress())
    {
        log<level::INFO>("Software path interface add signal received");

        // Set status to code update in progress.
        // Interface added signal triggered multiple times in code update path,
        // it's due to additional interfaces added by the software manager app
        // after the version interface is created.
        // Device tree data collection is required only for the first trigger
        setSoftwareUpdateProgress(true);

        try
        {
            // Colect device tree data
            openpower::phal::fwupdate::exportDevtree();
        }
        catch (const fs::filesystem_error& e)
        {
            log<level::ERR>(
                std::format("Filesystem error reported Error:({})", e.what())
                    .c_str());
            throw std::runtime_error(e.what());
        }

        log<level::INFO>("Successfully exported devtree attribute data");
    }

    return;
}

void exportDevtree()
{
    constexpr auto ERROR_DEVTREE_BACKUP =
        "org.open_power.PHAL.Error.devtreeBackup";

    // Check devtree export filter file is present
    auto path = fs::path(DEVTREE_EXPORT_FILTER_FILE);
    if (!fs::exists(path))
    {
        log<level::ERR>(
            std::format("devtree export filter file is not available: ({})",
                        DEVTREE_EXPORT_FILTER_FILE)
                .c_str());
        openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
        return;
    }

    // delete export data file if present
    auto expFile = fs::path(DEVTREE_EXP_FILE);
    if (fs::exists(expFile))
    {
        fs::remove_all(expFile);
    }
    else
    {
        // create directory
        fs::create_directory(expFile.parent_path());
    }

    // Update PDBG_DTB value
    openpower::phal::setDevtreeEnv();

    // Update PDATA_INFODB value
    openpower::phal::setPdataInfoDBEnv();

    int status = 0;
    pid_t pid = fork();
    if (pid == 0)
    {
        std::string cmd("/usr/bin/attributes ");
        cmd += "export ";
        cmd += DEVTREE_EXPORT_FILTER_FILE;
        cmd += " > ";
        cmd += DEVTREE_EXP_FILE;
        execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);

        auto error = errno;
        log<level::ERR>(std::format("Error occurred during attributes function "
                                    "execution, errno({})",
                                    error)
                            .c_str());
        // Creating PEL at one place.
    }
    else if (pid > 0)
    {
        waitpid(pid, &status, 0);
        if (WEXITSTATUS(status))
        {
            log<level::ERR>("Failed to collect attribute export data");
            openpower::pel::createPEL(ERROR_DEVTREE_BACKUP);
        }
    }
    else
    {
        log<level::ERR>("exportDevtree fork() failed");
        std::runtime_error("exportDevtree fork() failed");
    }
}

} // namespace fwupdate
} // namespace phal
} // namespace openpower
