// Copyright (c) 2012 The Chromium 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 "base/metrics/histogram_base.h"

#include <limits.h>

#include <memory>
#include <utility>

#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/sparse_histogram.h"
#include "base/metrics/statistics_recorder.h"
#include "base/pickle.h"
#include "base/process/process_handle.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"

namespace base {

std::string HistogramTypeToString(HistogramType type) {
  switch (type) {
    case HISTOGRAM:
      return "HISTOGRAM";
    case LINEAR_HISTOGRAM:
      return "LINEAR_HISTOGRAM";
    case BOOLEAN_HISTOGRAM:
      return "BOOLEAN_HISTOGRAM";
    case CUSTOM_HISTOGRAM:
      return "CUSTOM_HISTOGRAM";
    case SPARSE_HISTOGRAM:
      return "SPARSE_HISTOGRAM";
  }
  NOTREACHED();
  return "UNKNOWN";
}

HistogramBase* DeserializeHistogramInfo(PickleIterator* iter) {
  int type;
  if (!iter->ReadInt(&type))
    return NULL;

  switch (type) {
    case HISTOGRAM:
      return Histogram::DeserializeInfoImpl(iter);
    case LINEAR_HISTOGRAM:
      return LinearHistogram::DeserializeInfoImpl(iter);
    case BOOLEAN_HISTOGRAM:
      return BooleanHistogram::DeserializeInfoImpl(iter);
    case CUSTOM_HISTOGRAM:
      return CustomHistogram::DeserializeInfoImpl(iter);
    case SPARSE_HISTOGRAM:
      return SparseHistogram::DeserializeInfoImpl(iter);
    default:
      return NULL;
  }
}

const HistogramBase::Sample HistogramBase::kSampleType_MAX = INT_MAX;
HistogramBase* HistogramBase::report_histogram_ = nullptr;

HistogramBase::HistogramBase(const std::string& name)
    : histogram_name_(name),
      flags_(kNoFlags) {}

HistogramBase::~HistogramBase() {}

void HistogramBase::CheckName(const StringPiece& name) const {
  DCHECK_EQ(histogram_name(), name);
}

void HistogramBase::SetFlags(int32_t flags) {
  HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_);
  subtle::NoBarrier_Store(&flags_, old_flags | flags);
}

void HistogramBase::ClearFlags(int32_t flags) {
  HistogramBase::Count old_flags = subtle::NoBarrier_Load(&flags_);
  subtle::NoBarrier_Store(&flags_, old_flags & ~flags);
}

void HistogramBase::AddTime(const TimeDelta& time) {
  Add(static_cast<Sample>(time.InMilliseconds()));
}

void HistogramBase::AddBoolean(bool value) {
  Add(value ? 1 : 0);
}

bool HistogramBase::SerializeInfo(Pickle* pickle) const {
  if (!pickle->WriteInt(GetHistogramType()))
    return false;
  return SerializeInfoImpl(pickle);
}

uint32_t HistogramBase::FindCorruption(
    const HistogramSamples& /*samples*/) const {
  // Not supported by default.
  return NO_INCONSISTENCIES;
}

void HistogramBase::WriteJSON(std::string* output) const {
  Count count;
  int64_t sum;
  std::unique_ptr<ListValue> buckets(new ListValue());
  GetCountAndBucketData(&count, &sum, buckets.get());
  std::unique_ptr<DictionaryValue> parameters(new DictionaryValue());
  GetParameters(parameters.get());

  JSONStringValueSerializer serializer(output);
  DictionaryValue root;
  root.SetString("name", histogram_name());
  root.SetInteger("count", count);
  root.SetDouble("sum", static_cast<double>(sum));
  root.SetInteger("flags", flags());
  root.Set("params", std::move(parameters));
  root.Set("buckets", std::move(buckets));
  root.SetInteger("pid", GetCurrentProcId());
  serializer.Serialize(root);
}

// static
void HistogramBase::EnableActivityReportHistogram(
    const std::string& process_type) {
  DCHECK(!report_histogram_);
  size_t existing = StatisticsRecorder::GetHistogramCount();
  if (existing != 0) {
    DVLOG(1) << existing
             << " histograms were created before reporting was enabled.";
  }

  std::string name =
      "UMA.Histograms.Activity" +
      (process_type.empty() ? process_type : "." + process_type);

  // Calling FactoryGet() here rather than using a histogram-macro works
  // around some problems with tests that could end up seeing the results
  // histogram when not expected due to a bad interaction between
  // HistogramTester and StatisticsRecorder.
  report_histogram_ = LinearHistogram::FactoryGet(
      name, 1, HISTOGRAM_REPORT_MAX, HISTOGRAM_REPORT_MAX + 1,
      kUmaTargetedHistogramFlag);
  report_histogram_->Add(HISTOGRAM_REPORT_CREATED);
}

void HistogramBase::FindAndRunCallback(HistogramBase::Sample sample) const {
  if ((flags() & kCallbackExists) == 0)
    return;

  StatisticsRecorder::OnSampleCallback cb =
      StatisticsRecorder::FindCallback(histogram_name());
  if (!cb.is_null())
    cb.Run(sample);
}

void HistogramBase::WriteAsciiBucketGraph(double current_size,
                                          double max_size,
                                          std::string* output) const {
  const int k_line_length = 72;  // Maximal horizontal width of graph.
  int x_count = static_cast<int>(k_line_length * (current_size / max_size)
                                 + 0.5);
  int x_remainder = k_line_length - x_count;

  while (0 < x_count--)
    output->append("-");
  output->append("O");
  while (0 < x_remainder--)
    output->append(" ");
}

const std::string HistogramBase::GetSimpleAsciiBucketRange(
    Sample sample) const {
  std::string result;
  if (kHexRangePrintingFlag & flags())
    StringAppendF(&result, "%#x", sample);
  else
    StringAppendF(&result, "%d", sample);
  return result;
}

void HistogramBase::WriteAsciiBucketValue(Count current,
                                          double scaled_sum,
                                          std::string* output) const {
  StringAppendF(output, " (%d = %3.1f%%)", current, current/scaled_sum);
}

// static
void HistogramBase::ReportHistogramActivity(const HistogramBase& histogram,
                                            ReportActivity activity) {
  if (!report_histogram_)
    return;

  const int32_t flags = histogram.flags_;
  HistogramReport report_type = HISTOGRAM_REPORT_MAX;
  switch (activity) {
    case HISTOGRAM_CREATED:
      report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_CREATED);
      switch (histogram.GetHistogramType()) {
        case HISTOGRAM:
          report_type = HISTOGRAM_REPORT_TYPE_LOGARITHMIC;
          break;
        case LINEAR_HISTOGRAM:
          report_type = HISTOGRAM_REPORT_TYPE_LINEAR;
          break;
        case BOOLEAN_HISTOGRAM:
          report_type = HISTOGRAM_REPORT_TYPE_BOOLEAN;
          break;
        case CUSTOM_HISTOGRAM:
          report_type = HISTOGRAM_REPORT_TYPE_CUSTOM;
          break;
        case SPARSE_HISTOGRAM:
          report_type = HISTOGRAM_REPORT_TYPE_SPARSE;
          break;
      }
      report_histogram_->Add(report_type);
      if (flags & kIsPersistent)
        report_histogram_->Add(HISTOGRAM_REPORT_FLAG_PERSISTENT);
      if ((flags & kUmaStabilityHistogramFlag) == kUmaStabilityHistogramFlag)
        report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_STABILITY);
      else if (flags & kUmaTargetedHistogramFlag)
        report_histogram_->Add(HISTOGRAM_REPORT_FLAG_UMA_TARGETED);
      break;

    case HISTOGRAM_LOOKUP:
      report_histogram_->Add(HISTOGRAM_REPORT_HISTOGRAM_LOOKUP);
      break;
  }
}

}  // namespace base
