#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::Id>(),
                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::Id>(),
            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, id, 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), id,
                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);
    }
}
