
#include "estoraged.hpp"
#include "getConfig.hpp"
#include "util.hpp"

#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/container/throw_exception.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <util.hpp>

#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <optional>
#include <string>

/*
 * Get the configuration objects from Entity Manager and create new D-Bus
 * objects for each one. This function can be called multiple times, in case
 * new configuration objects show up later.
 *
 * Note: Currently, eStoraged can only support 1 eMMC device.
 * Additional changes will be needed to support more than 1 eMMC, or to support
 * more types of storage devices.
 */
void createStorageObjects(
    sdbusplus::asio::object_server& objectServer,
    boost::container::flat_map<
        std::string, std::unique_ptr<estoraged::EStoraged>>& storageObjects,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{
    auto getter = std::make_shared<estoraged::GetStorageConfiguration>(
        dbusConnection,
        [&objectServer, &storageObjects](
            const estoraged::ManagedStorageType& storageConfigurations) {
        size_t numConfigObj = storageConfigurations.size();
        if (numConfigObj > 1)
        {
            lg2::error("eStoraged can only manage 1 eMMC device; found {NUM}",
                       "NUM", numConfigObj, "REDFISH_MESSAGE_ID",
                       std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
            return;
        }

        for (const std::pair<sdbusplus::message::object_path,
                             estoraged::StorageData>& storage :
             storageConfigurations)
        {
            const std::string& path = storage.first.str;

            if (storageObjects.find(path) != storageObjects.end())
            {
                /*
                 * We've already created this object, or at least
                 * attempted to.
                 */
                continue;
            }

            /* Get the properties from the config object. */
            const estoraged::StorageData& data = storage.second;

            /* Look for the device file. */
            const std::filesystem::path blockDevDir{"/sys/block"};
            auto deviceInfo = estoraged::util::findDevice(data, blockDevDir);
            if (!deviceInfo)
            {
                lg2::error("Device not found for path {PATH}", "PATH", path,
                           "REDFISH_MESSAGE_ID",
                           std::string("OpenBMC.0.1.CreateStorageObjectsFail"));
                /*
                 * Set a NULL pointer as a placeholder, so that we don't
                 * try and fail again later.
                 */
                storageObjects[path] = nullptr;
                continue;
            }

            std::filesystem::path deviceFile =
                std::move(deviceInfo->deviceFile);
            std::filesystem::path sysfsDir = std::move(deviceInfo->sysfsDir);
            std::string luksName = std::move(deviceInfo->luksName);
            std::string locationCode = std::move(deviceInfo->locationCode);
            uint64_t eraseMaxGeometry = deviceInfo->eraseMaxGeometry;
            uint64_t eraseMinGeometry = deviceInfo->eraseMinGeometry;

            uint64_t size = estoraged::util::findSizeOfBlockDevice(deviceFile);

            uint8_t lifeleft =
                estoraged::util::findPredictedMediaLifeLeftPercent(sysfsDir);
            std::string partNumber = estoraged::util::getPartNumber(sysfsDir);
            std::string serialNumber =
                estoraged::util::getSerialNumber(sysfsDir);
            const std::string& driveType = deviceInfo->driveType;
            const std::string& driveProtocol = deviceInfo->driveProtocol;
            /* Create the storage object. */
            storageObjects[path] = std::make_unique<estoraged::EStoraged>(
                objectServer, path, deviceFile, luksName, size, lifeleft,
                partNumber, serialNumber, locationCode, eraseMaxGeometry,
                eraseMinGeometry, driveType, driveProtocol);
            lg2::info("Created eStoraged object for path {PATH}", "PATH", path,
                      "REDFISH_MESSAGE_ID",
                      std::string("OpenBMC.0.1.CreateStorageObjects"));
        }
    });
    getter->getConfiguration();
}

int main(void)
{
    try
    {
        // setup connection to dbus
        boost::asio::io_context io;
        auto conn = std::make_shared<sdbusplus::asio::connection>(io);
        // request D-Bus server name.
        conn->request_name("xyz.openbmc_project.eStoraged");
        sdbusplus::asio::object_server server(conn);
        boost::container::flat_map<std::string,
                                   std::unique_ptr<estoraged::EStoraged>>
            storageObjects;

        boost::asio::post(
            io, [&]() { createStorageObjects(server, storageObjects, conn); });

        /*
         * Set up an event handler to process any new configuration objects
         * that show up later.
         */
        boost::asio::deadline_timer filterTimer(io);
        std::function<void(sdbusplus::message_t&)> eventHandler =
            [&](sdbusplus::message_t& message) {
            if (message.is_method_error())
            {
                lg2::error("eventHandler callback method error");
                return;
            }
            /*
             * This implicitly cancels the timer, if it's already pending.
             * If there's a burst of events within a short period, we want
             * to handle them all at once. So, we will wait this long for no
             * more events to occur, before processing them.
             */
            filterTimer.expires_from_now(boost::posix_time::seconds(1));

            filterTimer.async_wait([&](const boost::system::error_code& ec) {
                if (ec == boost::asio::error::operation_aborted)
                {
                    /* we were canceled */
                    return;
                }
                if (ec)
                {
                    lg2::error("timer error");
                    return;
                }
                createStorageObjects(server, storageObjects, conn);
            });
        };

        auto match = std::make_unique<sdbusplus::bus::match_t>(
            static_cast<sdbusplus::bus_t&>(*conn),
            "type='signal',member='PropertiesChanged',path_namespace='" +
                std::string("/xyz/openbmc_project/inventory") +
                "',arg0namespace='" + estoraged::emmcConfigInterface + "'",
            eventHandler);

        lg2::info("Storage management service is running", "REDFISH_MESSAGE_ID",
                  std::string("OpenBMC.1.0.ServiceStarted"));

        io.run();
        return 0;
    }
    catch (const std::exception& e)
    {
        lg2::error(e.what(), "REDFISH_MESSAGE_ID",
                   std::string("OpenBMC.1.0.ServiceException"));

        return 2;
    }
    return 1;
}
