// 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 <cobalt-client/cpp/histogram.h>

#include <float.h>

#include <cmath>
#include <cstring>
#include <limits>

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

bool HistogramFlush(const HistogramOptions& 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
