#include "report_factory.hpp"

#include "metric.hpp"
#include "report.hpp"
#include "sensor.hpp"
#include "utils/clock.hpp"
#include "utils/conversion.hpp"
#include "utils/dbus_mapper.hpp"
#include "utils/transform.hpp"

ReportFactory::ReportFactory(
    std::shared_ptr<sdbusplus::asio::connection> bus,
    const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
    SensorCache& sensorCache) :
    bus(std::move(bus)), objServer(objServer), sensorCache(sensorCache)
{}

std::unique_ptr<interfaces::Report> ReportFactory::make(
    const std::string& id, const std::string& name,
    const ReportingType reportingType,
    const std::vector<ReportAction>& reportActions, Milliseconds period,
    uint64_t appendLimit, const ReportUpdates reportUpdates,
    interfaces::ReportManager& reportManager,
    interfaces::JsonStorage& reportStorage,
    std::vector<LabeledMetricParameters> labeledMetricParams, bool enabled,
    Readings readings) const
{
    auto metrics = utils::transform(labeledMetricParams,
                                    [this](const LabeledMetricParameters& param)
                                        -> std::shared_ptr<interfaces::Metric> {
        namespace ts = utils::tstring;

        return std::make_shared<Metric>(
            getSensors(param.at_label<ts::SensorPath>()),
            param.at_label<ts::OperationType>(),
            param.at_label<ts::CollectionTimeScope>(),
            param.at_label<ts::CollectionDuration>(),
            std::make_unique<Clock>());
    });

    return std::make_unique<Report>(
        bus->get_io_context(), objServer, id, name, reportingType,
        reportActions, period, appendLimit, reportUpdates, reportManager,
        reportStorage, std::move(metrics), *this, enabled,
        std::make_unique<Clock>(), std::move(readings));
}

void ReportFactory::updateMetrics(
    std::vector<std::shared_ptr<interfaces::Metric>>& metrics, bool enabled,
    const std::vector<LabeledMetricParameters>& labeledMetricParams) const
{
    std::vector<std::shared_ptr<interfaces::Metric>> oldMetrics = metrics;
    std::vector<std::shared_ptr<interfaces::Metric>> newMetrics;

    for (const auto& labeledMetricParam : labeledMetricParams)
    {
        auto existing = std::find_if(oldMetrics.begin(), oldMetrics.end(),
                                     [labeledMetricParam](auto metric) {
            return labeledMetricParam == metric->dumpConfiguration();
        });

        if (existing != oldMetrics.end())
        {
            newMetrics.emplace_back(*existing);
            oldMetrics.erase(existing);
            continue;
        }

        namespace ts = utils::tstring;
        newMetrics.emplace_back(std::make_shared<Metric>(
            getSensors(labeledMetricParam.at_label<ts::SensorPath>()),
            labeledMetricParam.at_label<ts::OperationType>(),
            labeledMetricParam.at_label<ts::CollectionTimeScope>(),
            labeledMetricParam.at_label<ts::CollectionDuration>(),
            std::make_unique<Clock>()));

        if (enabled)
        {
            newMetrics.back()->initialize();
        }
    }

    if (enabled)
    {
        for (auto& metric : oldMetrics)
        {
            metric->deinitialize();
        }
    }

    metrics = std::move(newMetrics);
}

Sensors ReportFactory::getSensors(
    const std::vector<LabeledSensorInfo>& sensorPaths) const
{
    using namespace utils::tstring;

    return utils::transform(sensorPaths,
                            [this](const LabeledSensorInfo& sensorPath)
                                -> std::shared_ptr<interfaces::Sensor> {
        return sensorCache.makeSensor<Sensor>(
            sensorPath.at_label<Service>(), sensorPath.at_label<Path>(),
            sensorPath.at_label<Metadata>(), bus->get_io_context(), bus);
    });
}

std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
    boost::asio::yield_context& yield,
    const ReadingParameters& metricParams) const
{
    if (metricParams.empty())
    {
        return {};
    }

    auto tree = utils::getSubTreeSensors(yield, bus);
    return getMetricParamsFromSensorTree(metricParams, tree);
}

std::vector<LabeledMetricParameters> ReportFactory::convertMetricParams(
    const ReadingParameters& metricParams) const
{
    if (metricParams.empty())
    {
        return {};
    }

    auto tree = utils::getSubTreeSensors(bus);
    return getMetricParamsFromSensorTree(metricParams, tree);
}

std::vector<LabeledMetricParameters>
    ReportFactory::getMetricParamsFromSensorTree(
        const ReadingParameters& metricParams,
        const std::vector<utils::SensorTree>& tree) const
{
    try
    {
        return utils::transform(metricParams, [&tree](const auto& item) {
            auto [sensorPaths, operationType, collectionTimeScope,
                  collectionDuration] = item;

            std::vector<LabeledSensorInfo> sensorParameters;

            for (const auto& [sensorPath, metadata] : sensorPaths)
            {
                auto it = std::find_if(tree.begin(), tree.end(),
                                       [path = sensorPath](const auto& v) {
                    return v.first == path;
                });

                if (it != tree.end() && it->second.size() == 1)
                {
                    const auto& [service, ifaces] = it->second.front();
                    sensorParameters.emplace_back(service, sensorPath,
                                                  metadata);
                }
            }

            if (sensorParameters.size() != sensorPaths.size())
            {
                throw errors::InvalidArgument("ReadingParameters",
                                              "Service not found.");
            }

            if (operationType.empty())
            {
                operationType = utils::enumToString(OperationType::avg);
            }
            else if (operationType == "SINGLE")
            {
                operationType = utils::enumToString(OperationType::avg);
                collectionTimeScope =
                    utils::enumToString(CollectionTimeScope::point);
            }

            if (collectionTimeScope.empty())
            {
                collectionTimeScope =
                    utils::enumToString(CollectionTimeScope::point);
            }

            return LabeledMetricParameters(
                std::move(sensorParameters),
                utils::toOperationType(operationType),
                utils::toCollectionTimeScope(collectionTimeScope),
                CollectionDuration(Milliseconds(collectionDuration)));
        });
    }
    catch (const errors::InvalidArgument& e)
    {
        if (e.propertyName == "ReadingParameters")
        {
            throw;
        }

        using namespace std::literals::string_literals;
        throw errors::InvalidArgument("ReadingParameters."s + e.propertyName);
    }
}
