// Copyright 2014 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 "cobalt/media/formats/common/stream_parser_test_base.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/bind.h"
#include "cobalt/media/base/media_log.h"
#include "cobalt/media/base/media_track.h"
#include "cobalt/media/base/media_tracks.h"
#include "cobalt/media/base/test_data_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace media {

static std::string BufferQueueToString(
    const StreamParser::BufferQueue& buffers) {
  std::stringstream ss;

  ss << "{";
  for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
       itr != buffers.end(); ++itr) {
    ss << " " << (*itr)->timestamp().InMilliseconds();
    if ((*itr)->is_key_frame()) ss << "K";
  }
  ss << " }";

  return ss.str();
}

StreamParserTestBase::StreamParserTestBase(
    std::unique_ptr<StreamParser> stream_parser)
    : parser_(std::move(stream_parser)) {
  parser_->Init(
      base::Bind(&StreamParserTestBase::OnInitDone, base::Unretained(this)),
      base::Bind(&StreamParserTestBase::OnNewConfig, base::Unretained(this)),
      base::Bind(&StreamParserTestBase::OnNewBuffers, base::Unretained(this)),
      true,
      base::Bind(&StreamParserTestBase::OnKeyNeeded, base::Unretained(this)),
      base::Bind(&StreamParserTestBase::OnNewSegment, base::Unretained(this)),
      base::Bind(&StreamParserTestBase::OnEndOfSegment, base::Unretained(this)),
      new MediaLog());
}

StreamParserTestBase::~StreamParserTestBase() {}

std::string StreamParserTestBase::ParseFile(const std::string& filename,
                                            int append_bytes) {
  results_stream_.clear();
  scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile(filename);
  EXPECT_TRUE(
      AppendDataInPieces(buffer->data(), buffer->data_size(), append_bytes));
  return results_stream_.str();
}

std::string StreamParserTestBase::ParseData(const uint8_t* data,
                                            size_t length) {
  results_stream_.clear();
  EXPECT_TRUE(AppendDataInPieces(data, length, length));
  return results_stream_.str();
}

bool StreamParserTestBase::AppendDataInPieces(const uint8_t* data,
                                              size_t length,
                                              size_t piece_size) {
  const uint8_t* start = data;
  const uint8_t* end = data + length;
  while (start < end) {
    size_t append_size = std::min(piece_size, static_cast<size_t>(end - start));
    if (!parser_->Parse(start, append_size)) return false;
    start += append_size;
  }
  return true;
}

void StreamParserTestBase::OnInitDone(
    const StreamParser::InitParameters& params) {
  EXPECT_TRUE(params.auto_update_timestamp_offset);
  DVLOG(1) << __FUNCTION__ << "(" << params.duration.InMilliseconds() << ", "
           << params.auto_update_timestamp_offset << ")";
}

bool StreamParserTestBase::OnNewConfig(
    std::unique_ptr<MediaTracks> tracks,
    const StreamParser::TextTrackConfigMap& text_config) {
  DVLOG(1) << __FUNCTION__ << ": got " << tracks->tracks().size() << " tracks";
  EXPECT_EQ(tracks->tracks().size(), 1u);
  const auto& track = tracks->tracks()[0];
  EXPECT_EQ(track->type(), MediaTrack::Audio);
  audio_track_id_ = track->bytestream_track_id();
  last_audio_config_ = tracks->getAudioConfig(track->bytestream_track_id());
  EXPECT_TRUE(last_audio_config_.IsValidConfig());
  return true;
}

bool StreamParserTestBase::OnNewBuffers(
    const StreamParser::BufferQueueMap& buffer_queue_map) {
  EXPECT_EQ(1u, buffer_queue_map.size());
  const auto& itr_audio = buffer_queue_map.find(audio_track_id_);
  EXPECT_NE(buffer_queue_map.end(), itr_audio);
  const StreamParser::BufferQueue& audio_buffers = itr_audio->second;
  EXPECT_FALSE(audio_buffers.empty());

  // Ensure that track ids are properly assigned on all emitted buffers.
  for (const auto& buf : audio_buffers) {
    EXPECT_EQ(audio_track_id_, buf->track_id());
  }

  const std::string buffers_str = BufferQueueToString(audio_buffers);
  DVLOG(1) << __FUNCTION__ << " : " << buffers_str;
  results_stream_ << buffers_str;
  return true;
}

void StreamParserTestBase::OnKeyNeeded(EmeInitDataType type,
                                       const std::vector<uint8_t>& init_data) {
  DVLOG(1) << __FUNCTION__ << "(" << static_cast<int>(type) << ", "
           << init_data.size() << ")";
}

void StreamParserTestBase::OnNewSegment() {
  DVLOG(1) << __FUNCTION__;
  results_stream_ << "NewSegment";
}

void StreamParserTestBase::OnEndOfSegment() {
  DVLOG(1) << __FUNCTION__;
  results_stream_ << "EndOfSegment";
}

}  // namespace media
