// 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_samples.h"

#include "base/compiler_specific.h"
#include "base/pickle.h"

namespace base {

namespace {

class SampleCountPickleIterator : public SampleCountIterator {
 public:
  explicit SampleCountPickleIterator(PickleIterator* iter);

  virtual bool Done() const OVERRIDE;
  virtual void Next() OVERRIDE;
  virtual void Get(HistogramBase::Sample* min,
                   HistogramBase::Sample* max,
                   HistogramBase::Count* count) const OVERRIDE;
 private:
  PickleIterator* const iter_;

  HistogramBase::Sample min_;
  HistogramBase::Sample max_;
  HistogramBase::Count count_;
  bool is_done_;
};

SampleCountPickleIterator::SampleCountPickleIterator(PickleIterator* iter)
    : iter_(iter),
      is_done_(false) {
  Next();
}

bool SampleCountPickleIterator::Done() const {
  return is_done_;
}

void SampleCountPickleIterator::Next() {
  DCHECK(!Done());
  if (!iter_->ReadInt(&min_) ||
      !iter_->ReadInt(&max_) ||
      !iter_->ReadInt(&count_))
    is_done_ = true;
}

void SampleCountPickleIterator::Get(HistogramBase::Sample* min,
                                    HistogramBase::Sample* max,
                                    HistogramBase::Count* count) const {
  DCHECK(!Done());
  *min = min_;
  *max = max_;
  *count = count_;
}

}  // namespace

HistogramSamples::HistogramSamples() : sum_(0), redundant_count_(0) {}

HistogramSamples::~HistogramSamples() {}

void HistogramSamples::Add(const HistogramSamples& other) {
  sum_ += other.sum();
  redundant_count_ += other.redundant_count();
  bool success = AddSubtractImpl(other.Iterator().get(), ADD);
  DCHECK(success);
}

bool HistogramSamples::AddFromPickle(PickleIterator* iter) {
  int64 sum;
  HistogramBase::Count redundant_count;

  if (!iter->ReadInt64(&sum) || !iter->ReadInt(&redundant_count))
    return false;
  sum_ += sum;
  redundant_count_ += redundant_count;

  SampleCountPickleIterator pickle_iter(iter);
  return AddSubtractImpl(&pickle_iter, ADD);
}

void HistogramSamples::Subtract(const HistogramSamples& other) {
  sum_ -= other.sum();
  redundant_count_ -= other.redundant_count();
  bool success = AddSubtractImpl(other.Iterator().get(), SUBTRACT);
  DCHECK(success);
}

bool HistogramSamples::Serialize(Pickle* pickle) const {
  if (!pickle->WriteInt64(sum_) || !pickle->WriteInt(redundant_count_))
    return false;

  HistogramBase::Sample min;
  HistogramBase::Sample max;
  HistogramBase::Count count;
  for (scoped_ptr<SampleCountIterator> it = Iterator();
       !it->Done();
       it->Next()) {
    it->Get(&min, &max, &count);
    if (!pickle->WriteInt(min) ||
        !pickle->WriteInt(max) ||
        !pickle->WriteInt(count))
      return false;
  }
  return true;
}

void HistogramSamples::IncreaseSum(int64 diff) {
  sum_ += diff;
}

void HistogramSamples::IncreaseRedundantCount(HistogramBase::Count diff) {
  base::subtle::NoBarrier_Store(&redundant_count_,
      base::subtle::NoBarrier_Load(&redundant_count_) + diff);
}

SampleCountIterator::~SampleCountIterator() {}

bool SampleCountIterator::GetBucketIndex(size_t* index) const {
  DCHECK(!Done());
  return false;
}

}  // namespace base
