// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <float.h>
#include <limits>
#include <math.h>
#include <string.h>

#include <cobalt-client/cpp/histogram.h>

#include <cobalt-client/cpp/histogram-internal.h>
#include <cobalt-client/cpp/metric-options.h>

namespace cobalt_client {
namespace internal {
namespace {

double GetLinearBucketValue(uint32_t bucket_index, uint32_t bucket_count,
                            const HistogramOptions& options) {
    if (bucket_index == 0) {
        return -DBL_MAX;
    }
    return options.scalar * (bucket_index - 1) + options.offset;
}

double GetExponentialBucketValue(uint32_t bucket_index, uint32_t bucket_count,
                                 const HistogramOptions& options) {
    if (bucket_index == 0) {
        return -DBL_MAX;
    }
    return options.scalar * pow(options.base, bucket_index - 1) + options.offset;
}

uint32_t GetLinearBucket(double value, uint32_t bucket_count, const HistogramOptions& options,
                         double max_value) {
    if (value < options.offset) {
        return 0;
    } else if (value >= max_value) {
        return bucket_count - 1;
    }
    double unshifted_bucket = (value - options.offset) / options.scalar;
    ZX_DEBUG_ASSERT(unshifted_bucket >= std::numeric_limits<uint32_t>::min());
    ZX_DEBUG_ASSERT(unshifted_bucket <= std::numeric_limits<uint32_t>::max());
    return static_cast<uint32_t>(unshifted_bucket) + 1;
}

uint32_t GetExponentialBucket(double value, uint32_t bucket_count, const HistogramOptions& options,
                              double max_value) {
    if (value < options.scalar + options.offset) {
        return 0;
    } else if (value >= max_value) {
        return bucket_count - 1;
    }

    double diff = value - options.offset;
    uint32_t unshifted_bucket = 0;
    // Only use the formula if the difference is positive.
    if (diff >= options.scalar) {
        unshifted_bucket =
            static_cast<uint32_t>(floor((log2(diff) - log2(options.scalar)) / log2(options.base)));
    }
    ZX_DEBUG_ASSERT(unshifted_bucket <= bucket_count + 1);

    double lower_bound = GetExponentialBucketValue(unshifted_bucket + 1, bucket_count, options);
    if (lower_bound > value) {
        --unshifted_bucket;
    }
    return unshifted_bucket + 1;
}

void LoadExponential(uint32_t bucket_count, HistogramOptions* options) {
    options->max_value = options->scalar * pow(options->base, bucket_count) + options->offset;
    options->map_fn = [](double val, uint32_t bucket_count, const HistogramOptions& options) {
        return internal::GetExponentialBucket(val, bucket_count, options, options.max_value);
    };
    options->reverse_map_fn = internal::GetExponentialBucketValue;
}

void LoadLinear(uint32_t bucket_count, HistogramOptions* options) {
    options->max_value = static_cast<double>(options->scalar * bucket_count + options->offset);
    options->map_fn = [](double val, uint32_t bucket_count, const HistogramOptions& options) {
        return internal::GetLinearBucket(val, bucket_count, options, options.max_value);
    };
    options->reverse_map_fn = internal::GetLinearBucketValue;
}

} // namespace

void InitBucketBuffer(HistogramBucket* buckets, uint32_t bucket_count) {
    for (uint32_t i = 0; i < bucket_count; ++i) {
        buckets[i].count = 0;
        buckets[i].index = i;
    }
}

void InitLazily(const MetricOptions& options, HistogramBucket* buckets, uint32_t num_buckets,
                RemoteMetricInfo* metric_info) {
    ZX_DEBUG_ASSERT(!options.IsLazy());
    *metric_info = RemoteMetricInfo::From(options);
    InitBucketBuffer(buckets, num_buckets);
}

bool HistogramFlush(const RemoteMetricInfo& metric_info, Logger* logger,
                    BaseCounter<uint64_t>* buckets, HistogramBucket* bucket_buffer,
                    uint32_t num_buckets) {
    // Sets every bucket back to 0, not all buckets will be at the same instant, but
    // eventual consistency in the backend is good enough.
    for (uint32_t bucket_index = 0; bucket_index < num_buckets; ++bucket_index) {
        bucket_buffer[bucket_index].count = buckets[bucket_index].Exchange();
    }
    return logger->Log(metric_info, bucket_buffer, num_buckets);
}

void HistogramUndoFlush(BaseCounter<uint64_t>* buckets, HistogramBucket* bucket_buffer,
                        uint32_t num_buckets) {
    for (uint32_t bucket_index = 0; bucket_index < num_buckets; ++bucket_index) {
        buckets[bucket_index].Increment(bucket_buffer[bucket_index].count);
    }
}

} // namespace internal

HistogramOptions::HistogramOptions(const HistogramOptions&) = default;
HistogramOptions& HistogramOptions::operator=(const HistogramOptions&) = default;

HistogramOptions HistogramOptions::Exponential(uint32_t bucket_count, int64_t max) {
    return Exponential(bucket_count, 0, max);
}

HistogramOptions HistogramOptions::Exponential(uint32_t bucket_count, int64_t min, int64_t max) {
    ZX_DEBUG_ASSERT_MSG(min < max, "min must be smaller than max.");
    // 2^bucket - 1 is the lower bound of the overflow bucket.
    uint64_t overflow_limit = (1 << bucket_count) - 1;
    uint64_t range = max - min;
    uint32_t scalar = 1;

    // If max is past the overflow limit we need to scale up, and the minimum is 1.
    if (range - overflow_limit > 0) {
        scalar = static_cast<uint32_t>(range / overflow_limit);
        if (range % overflow_limit != 0) {
            scalar++;
        }
    }
    ZX_DEBUG_ASSERT_MSG(2 * range >= scalar * overflow_limit,
                        "range is too small for the number of buckets.");

    return CustomizedExponential(bucket_count, 2, scalar, min);
}

HistogramOptions HistogramOptions::CustomizedExponential(uint32_t bucket_count, uint32_t base,
                                                         uint32_t scalar, int64_t min) {
    HistogramOptions options;
    options.type = Type::kExponential;
    options.base = static_cast<double>(base);
    options.scalar = static_cast<double>(scalar);
    options.offset = static_cast<double>(min - scalar);
    internal::LoadExponential(bucket_count, &options);
    return options;
}

HistogramOptions HistogramOptions::Linear(uint32_t bucket_count, int64_t max) {
    return Linear(bucket_count, 0, max);
}

HistogramOptions HistogramOptions::Linear(uint32_t bucket_count, int64_t min, int64_t max) {
    ZX_DEBUG_ASSERT_MSG(min < max, "min must be smaller than max.");
    uint64_t range = max - min;
    ZX_DEBUG_ASSERT_MSG(range >= bucket_count, "range is too small for the number of buckets.");
    uint64_t scalar = range / bucket_count;
    if (range % bucket_count != 0) {
        scalar++;
    }
    ZX_DEBUG_ASSERT_MSG(scalar <= std::numeric_limits<uint32_t>::max(), "scalar overflow\n");
    return CustomizedLinear(bucket_count, static_cast<uint32_t>(scalar), min);
}

HistogramOptions HistogramOptions::CustomizedLinear(uint32_t bucket_count, uint32_t step_size,
                                                    int64_t min) {
    HistogramOptions options;
    options.scalar = static_cast<double>(step_size);
    options.offset = static_cast<double>(min);
    options.type = Type::kLinear;
    internal::LoadLinear(bucket_count, &options);
    return options;
}

bool HistogramOptions::IsValid() const {
    switch (type) {
    case Type::kExponential:
        if (base == 0) {
            return false;
        }
        __FALLTHROUGH;
    case Type::kLinear:
        if (scalar == 0) {
            return false;
        }
        break;
    }

    return true;
}

} // namespace cobalt_client
