#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);
    }
}
