#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::printf("%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;
}
