#include <algorithm>
#include <string>
#include <sstream>
#include <cmath>

#include "vtr_log.h"
#include "vtr_assert.h"
#include "vtr_util.h"

#include "histogram.h"

std::vector<HistogramBucket> build_histogram(std::vector<float> values, size_t num_bins, float min_value, float max_value) {
    std::vector<HistogramBucket> histogram;

    if (values.empty()) return histogram;

    if (std::isnan(min_value)) {
        min_value = *std::min_element(values.begin(), values.end());
    }
    if (std::isnan(max_value)) {
        max_value = *std::max_element(values.begin(), values.end());
    }

    //Determine the bin size
    float range = max_value - min_value;
    float bin_size = range / num_bins;

    //Create the buckets
    float bucket_min = min_value;
    for (size_t ibucket = 0; ibucket < num_bins; ++ibucket) {
        float bucket_max = bucket_min + bin_size;

        histogram.emplace_back(bucket_min, bucket_max);

        bucket_min = bucket_max;
    }

    //To avoid round-off errors we force the max value of the last bucket equal to the max value
    histogram[histogram.size() - 1].max_value = max_value;

    //Count the values into the buckets
    auto comp = [](const HistogramBucket& bucket, float value) {
        return bucket.max_value < value;
    };
    for (auto value : values) {
        //Find the bucket who's max is less than the current slack

        auto iter = std::lower_bound(histogram.begin(), histogram.end(), value, comp);
        VTR_ASSERT(iter != histogram.end());

        iter->count++;
    }

    return histogram;
}

void print_histogram(std::vector<HistogramBucket> histogram) {
    size_t char_width = 80;

    auto lines = format_histogram(histogram, char_width);

    for (auto line : lines) {
        VTR_LOG("%s\n", line.c_str());
    }
}

std::vector<std::string> format_histogram(std::vector<HistogramBucket> histogram, size_t width) {
    std::vector<std::string> lines;

    //Determine the maximum and total count
    size_t max_count = 0;
    size_t total_count = 0;
    for(const HistogramBucket& bucket : histogram) {
        max_count = std::max(max_count, bucket.count);
        total_count += bucket.count;
    }

    if(max_count == 0) return lines; //Nothing to do

    int count_digits = ceil(log10(max_count));

    //Determine the maximum prefix length
    size_t bar_len = width
                     - (18 +3) //bucket prefix
                     - count_digits
                     - 7 //percentage
                     - 2; //-2 for " |" appended after count

    for(size_t ibucket = 0; ibucket < histogram.size(); ++ibucket) {
        std::string line;

        float pct = histogram[ibucket].count / float(total_count)  * 100;

        line += vtr::string_fmt("[% 9.2g:% 9.2g) %*zu (%4.1f%) |", histogram[ibucket].min_value, histogram[ibucket].max_value, count_digits, histogram[ibucket].count, pct);

        size_t num_chars = std::round((double(histogram[ibucket].count) / max_count) * bar_len);
        for(size_t i = 0; i < num_chars; ++i) {
            line += "*";
        }

        lines.push_back(line);
    }

    return lines;
}
