// Copyright 2023 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/media/base/cval_stats.h"

#include <numeric>

namespace cobalt {
namespace media {

CValContainer::CValContainer(std::string name,
                             int max_samples_before_calculation)
    : cval_name_{name},
      max_samples_before_calculation_{max_samples_before_calculation},
      latest_{
          "Media." + name + ".Latest", {}, "Latest sample in microseconds."},
      average_{
          "Media." + name + ".Average", {}, "Average sample in microseconds."},
      maximum_{
          "Media." + name + ".Maximum", {}, "Maximum sample in microseconds."},
      median_{
          "Media." + name + ".Median", {}, "Median sample in microseconds."},
      minimum_{
          "Media." + name + ".Minimum", {}, "Minimum sample in microseconds."} {
}

void CValContainer::UpdateCVal(TimeDelta event_time) {
  latest_ = event_time;
  accumulated_sample_count_++;

  if (!first_sample_added_) {
    minimum_ = event_time;
    maximum_ = event_time;
    first_sample_added_ = true;
  }

  samples_[sample_write_index_] = event_time;
  sample_write_index_ = (sample_write_index_ + 1) % kMaxSamples;

  if (accumulated_sample_count_ % max_samples_before_calculation_ == 0) {
    std::vector<TimeDelta> copy;
    int copy_size = std::min(accumulated_sample_count_, kMaxSamples);
    copy.reserve(copy_size);
    copy.assign(samples_, samples_ + copy_size);
    std::sort(copy.begin(), copy.end());
    if (copy.size() % 2 == 0) {
      median_ = (copy[copy.size() / 2 - 1] + copy[copy.size() / 2]) / 2;
    } else {
      median_ = copy[copy.size() / 2];
    }

    minimum_ = std::min(minimum_.value(), copy[0]);
    maximum_ = std::max(maximum_.value(), copy[copy.size() - 1]);

    auto local_average = std::accumulate(copy.begin(), copy.end(), TimeDelta());
    average_ += (local_average - average_.value()) / accumulated_sample_count_;
  }
}

CValStats::CValStats() {
  cval_containers_.emplace(
      std::piecewise_construct,
      std::forward_as_tuple(MediaTiming::SbPlayerCreate),
      std::forward_as_tuple("SbPlayerCreateTime",
                            kMediaDefaultMaxSamplesBeforeCalculation));
  cval_containers_.emplace(
      std::piecewise_construct,
      std::forward_as_tuple(MediaTiming::SbPlayerDestroy),
      std::forward_as_tuple("SbPlayerDestructionTime",
                            kMediaDefaultMaxSamplesBeforeCalculation));
  cval_containers_.emplace(
      std::piecewise_construct,
      std::forward_as_tuple(MediaTiming::SbPlayerWriteSamples),
      std::forward_as_tuple("SbPlayerWriteSamplesTime",
                            kMediaHighFrequencyMaxSamplesBeforeCalculation));
}

void CValStats::StartTimer(MediaTiming event_type,
                           std::string pipeline_identifier) {
  if (!enabled_) return;

  running_timers_[std::make_pair(event_type, pipeline_identifier)] =
      Time::Now();
}

void CValStats::StopTimer(MediaTiming event_type,
                          std::string pipeline_identifier) {
  if (!enabled_) return;

  auto key = std::make_pair(event_type, pipeline_identifier);
  DCHECK(running_timers_.find(key) != running_timers_.end());

  TimeDelta time_taken = Time::Now() - running_timers_[key];
  auto cval_container = cval_containers_.find(event_type);
  if (cval_container != cval_containers_.end()) {
    cval_container->second.UpdateCVal(time_taken);
  }
}

// for testing only
size_t CValStats::GetBufferIndexForTest() {
  DCHECK(cval_containers_.size() > 0);
  auto cval_container = cval_containers_.find(MediaTiming::SbPlayerCreate);
  if (cval_container != cval_containers_.end()) {
    return cval_container->second.GetSampleIndex();
  }
  return 0;
}

// for testing only
size_t CValStats::GetBufferSampleSizeForTest() {
  DCHECK(cval_containers_.size() > 0);
  auto cval_container = cval_containers_.find(MediaTiming::SbPlayerCreate);
  if (cval_container != cval_containers_.end()) {
    return cval_container->second.GetNumberSamples();
  }
  return 0;
}

}  // namespace media
}  // namespace cobalt
