#include "collection_function.hpp"

#include <cmath>

namespace details
{

class FunctionSingle : public CollectionFunction
{
  public:
    ReadingItem calculate(const std::vector<ReadingItem>& readings,
                          uint64_t) const override
    {
        return readings.back();
    }

    ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
                                            uint64_t timestamp) const override
    {
        readings.assign({readings.back()});
        return readings.back();
    }
};

class FunctionMinimum : public CollectionFunction
{
  public:
    ReadingItem calculate(const std::vector<ReadingItem>& readings,
                          uint64_t) const override
    {
        return *std::min_element(
            readings.begin(), readings.end(),
            [](const auto& left, const auto& right) {
                return std::make_tuple(!std::isfinite(left.second),
                                       left.second) <
                       std::make_tuple(!std::isfinite(right.second),
                                       right.second);
            });
    }

    ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
                                            uint64_t timestamp) const override
    {
        readings.assign({ReadingItem(calculate(readings, timestamp))});
        return readings.back();
    }
};

class FunctionMaximum : public CollectionFunction
{
  public:
    ReadingItem calculate(const std::vector<ReadingItem>& readings,
                          uint64_t) const override
    {
        return *std::max_element(
            readings.begin(), readings.end(),
            [](const auto& left, const auto& right) {
                return std::make_tuple(std::isfinite(left.second),
                                       left.second) <
                       std::make_tuple(std::isfinite(right.second),
                                       right.second);
            });
    }

    ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
                                            uint64_t timestamp) const override
    {
        readings.assign({ReadingItem(calculate(readings, timestamp))});
        return readings.back();
    }
};

class FunctionAverage : public CollectionFunction
{
  public:
    ReadingItem calculate(const std::vector<ReadingItem>& readings,
                          uint64_t timestamp) const override
    {
        auto valueSum = 0.0;
        auto timeSum = uint64_t{0};
        for (auto it = readings.begin(); it != std::prev(readings.end()); ++it)
        {
            if (std::isfinite(it->second))
            {
                const auto kt = std::next(it);
                const auto duration = kt->first - it->first;
                valueSum += it->second * duration;
                timeSum += duration;
            }
        }

        const auto duration = timestamp - readings.back().first;
        valueSum += readings.back().second * duration;
        timeSum += duration;

        return ReadingItem{timestamp, valueSum / timeSum};
    }

    ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
                                            uint64_t timestamp) const override
    {
        auto result = calculate(readings, timestamp);
        if (std::isfinite(result.second))
        {
            readings.assign({ReadingItem(readings.front().first, result.second),
                             ReadingItem(timestamp, readings.back().second)});
        }
        return result;
    }
};

class FunctionSummation : public CollectionFunction
{
  public:
    ReadingItem calculate(const std::vector<ReadingItem>& readings,
                          uint64_t timestamp) const override
    {
        auto valueSum = 0.0;
        for (auto it = readings.begin(); it != std::prev(readings.end()); ++it)
        {
            if (std::isfinite(it->second))
            {
                const auto kt = std::next(it);
                const auto duration = kt->first - it->first;
                valueSum += it->second * duration;
            }
        }

        const auto duration = timestamp - readings.back().first;
        valueSum += readings.back().second * duration;

        return ReadingItem{timestamp, valueSum};
    }

    ReadingItem calculateForStartupInterval(std::vector<ReadingItem>& readings,
                                            uint64_t timestamp) const override
    {
        auto result = calculate(readings, timestamp);
        if (std::isfinite(result.second) && timestamp > 0u)
        {
            readings.assign({ReadingItem(timestamp - 1u, result.second),
                             ReadingItem(timestamp, readings.back().second)});
        }
        return result;
    }
};

std::shared_ptr<CollectionFunction>
    makeCollectionFunction(OperationType operationType)
{
    using namespace std::string_literals;

    switch (operationType)
    {
        case OperationType::single:
            return std::make_shared<FunctionSingle>();
        case OperationType::min:
            return std::make_shared<FunctionMinimum>();
        case OperationType::max:
            return std::make_shared<FunctionMaximum>();
        case OperationType::avg:
            return std::make_shared<FunctionAverage>();
        case OperationType::sum:
            return std::make_shared<FunctionSummation>();
        default:
            throw std::runtime_error("op: "s +
                                     utils::enumToString(operationType) +
                                     " is not supported"s);
    }
}

} // namespace details
