#include "balancer_stats.h"

namespace NSrvKernel {
namespace {

void WriteLabels(const NMonitoring::TLabels& labels, const NMonitoring::IMetricEncoderPtr& encoder) {
    encoder->OnLabelsBegin();
    for (const auto& label : labels) {
        encoder->OnLabel(label.Name(), label.Value());
    }
    encoder->OnLabelsEnd();
}

}  // namespace

void EncodeSolomonResponse(NMonitoring::IMetricEncoderPtr& encoder, const TBalancerStats& stats)
{
    for (const auto& entry : stats.Counters) {
        encoder->OnMetricBegin(entry.MetricType);
        WriteLabels(entry.Labels, encoder);
        encoder->OnUint64(TInstant::Zero(), entry.Value);
        encoder->OnMetricEnd();
    }

    for (auto& entry : stats.Histograms) {
        encoder->OnMetricBegin(entry.MetricType);

        WriteLabels(entry.Labels, encoder);

        TVector<double> rightBounds;
        rightBounds.reserve(entry.Values.size());
        std::transform(
            entry.Values.begin() + 1,
            entry.Values.end(),
            std::back_inserter(rightBounds), [](const auto& point) {
                return point.first;
            }
        );

        TVector<ui64> aggregatedValues;
        aggregatedValues.reserve(entry.Values.size());
        std::transform(
            entry.Values.begin(),
            entry.Values.end(),
            std::back_inserter(aggregatedValues), [](const auto& point) {
                return point.second;
            }
        );

        auto hist = NMonitoring::ExplicitHistogram(rightBounds);
        for (size_t i = 0; i < rightBounds.size(); ++i) {
            hist->Collect(rightBounds[i], aggregatedValues[i]);
        }
        hist->Collect(rightBounds.back() + 1, aggregatedValues.back()); // Last bucket will be stored in "inf" field

        encoder->OnHistogram(TInstant::Zero(), hist->Snapshot());

        encoder->OnMetricEnd();
    }
}

}  // namespace NSrvKernel
