// 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 <math.h>
#include <string.h>

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

#include <cobalt-client/cpp/histogram-internal.h>
#include <cobalt-client/cpp/histogram-options.h>
#include <fbl/limits.h>
#include <fuchsia/cobalt/c/fidl.h>

namespace cobalt_client {
namespace internal {
namespace {

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

double GetExponentialBucketValue(uint32_t bucket_index, 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, const HistogramOptions& options, double max_value) {
    if (value < options.offset) {
        return 0;
    } else if (value >= max_value) {
        return options.bucket_count + 1;
    }
    double unshifted_bucket = (value - options.offset) / options.scalar;
    ZX_DEBUG_ASSERT(unshifted_bucket >= fbl::numeric_limits<uint32_t>::min());
    ZX_DEBUG_ASSERT(unshifted_bucket <= fbl::numeric_limits<uint32_t>::max());
    return static_cast<uint32_t>(unshifted_bucket) + 1;
}

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

    // Use bigger size double to perform the calculations to avoid precision errors near boundaries.
    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 <= options.bucket_count + 1);

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

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

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

} // namespace

BaseHistogram::BaseHistogram(uint32_t num_buckets) {
    buckets_.reserve(num_buckets);
    for (uint32_t i = 0; i < num_buckets; ++i) {
        buckets_.push_back(BaseCounter());
    }
}

BaseHistogram::BaseHistogram(BaseHistogram&& other) = default;

RemoteHistogram::RemoteHistogram(uint32_t num_buckets, uint32_t metric_id,
                                 const fbl::Vector<Metadata>& metadata)
    : BaseHistogram(num_buckets), buffer_(metadata), metric_id_(metric_id) {
    bucket_buffer_.reserve(num_buckets);
    for (uint32_t i = 0; i < num_buckets; ++i) {
        HistogramBucket bucket;
        bucket.count = 0;
        bucket.index = i;
        bucket_buffer_.push_back(bucket);
    }
    auto* buckets = buffer_.mutable_event_data();
    buckets->set_data(bucket_buffer_.get());
    buckets->set_count(bucket_buffer_.size());
}

RemoteHistogram::RemoteHistogram(RemoteHistogram&& other)
    : BaseHistogram(fbl::move(other)), buffer_(fbl::move(other.buffer_)),
      bucket_buffer_(fbl::move(other.bucket_buffer_)), metric_id_(other.metric_id_) {}

bool RemoteHistogram::Flush(const RemoteHistogram::FlushFn& flush_handler) {
    if (!buffer_.TryBeginFlush()) {
        return false;
    }

    // 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 < bucket_buffer_.size(); ++bucket_index) {
        bucket_buffer_[bucket_index].count = buckets_[bucket_index].Exchange();
    }

    flush_handler(metric_id_, buffer_, fbl::BindMember(&buffer_, &EventBuffer::CompleteFlush));
    return true;
}
} // namespace internal

HistogramOptions::HistogramOptions(const HistogramOptions& other)
    : base(other.base), scalar(other.scalar), offset(other.offset),
      bucket_count(other.bucket_count), type(other.type) {
    if (type == Type::kLinear) {
        internal::LoadLinear(this);
    } else {
        internal::LoadExponential(this);
    }
}

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

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

Histogram::Histogram(HistogramOptions* options, internal::RemoteHistogram* remote_histogram)
    : options_(options), remote_histogram_(remote_histogram) {}

Histogram::Histogram(const Histogram&) = default;
Histogram::Histogram(Histogram&&) = default;
Histogram& Histogram::operator=(const Histogram&) = default;
Histogram& Histogram::operator=(Histogram&&) = default;
Histogram::~Histogram() = default;

template <typename ValueType> void Histogram::Add(ValueType value, Histogram::Count times) {
    double dbl_value = static_cast<double>(value);
    uint32_t bucket = options_->map_fn(dbl_value, *options_);
    remote_histogram_->IncrementCount(bucket, times);
}

template <typename ValueType> Histogram::Count Histogram::GetRemoteCount(ValueType value) const {
    double dbl_value = static_cast<double>(value);
    uint32_t bucket = options_->map_fn(dbl_value, *options_);
    return remote_histogram_->GetCount(bucket);
}

// Supported template instantiations.
template void Histogram::Add<double>(double, Histogram::Count);
template void Histogram::Add<int32_t>(int32_t, Histogram::Count);
template void Histogram::Add<uint32_t>(uint32_t, Histogram::Count);
template void Histogram::Add<int64_t>(int64_t, Histogram::Count);
template void Histogram::Add<uint64_t>(uint64_t, Histogram::Count);

template Histogram::Count Histogram::GetRemoteCount<double>(double) const;
template Histogram::Count Histogram::GetRemoteCount<int32_t>(int32_t) const;
template Histogram::Count Histogram::GetRemoteCount<uint32_t>(uint32_t) const;
template Histogram::Count Histogram::GetRemoteCount<int64_t>(int64_t) const;
template Histogram::Count Histogram::GetRemoteCount<uint64_t>(uint64_t) const;

} // namespace cobalt_client
