// Copyright 2017 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 <memory>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "base/task/task_scheduler/task_scheduler.h"
#include "cobalt/base/wrap_main.h"
#include "cobalt/media/decoder_buffer_allocator.h"
#include "starboard/common/string.h"
#include "starboard/event.h"
#include "third_party/chromium/media/base/media_log.h"
#include "third_party/chromium/media/filters/chunk_demuxer.h"

namespace cobalt {
namespace media {
namespace sandbox {

namespace {

using ::media::ChunkDemuxer;
using ::media::DemuxerStream;

class DemuxerHostStub : public ::media::DemuxerHost {
  void OnBufferedTimeRangesChanged(
      const ::media::Ranges<base::TimeDelta>& ranges) override {}

  void SetDuration(base::TimeDelta duration) override {}

  void OnDemuxerError(::media::PipelineStatus error) override {}
};

void OnDemuxerOpen() {}

void OnEncryptedMediaInitData(::media::EmeInitDataType type,
                              const std::vector<uint8_t>& init_data) {}

void OnInitSegmentReceived(std::unique_ptr<::media::MediaTracks> tracks) {}

void OnDemuxerStatus(::media::PipelineStatus status) {}

std::string LoadFile(const std::string& file_name) {
  base::FilePath file_path(file_name);
  if (!file_path.IsAbsolute()) {
    base::FilePath content_path;
    base::PathService::Get(base::DIR_TEST_DATA, &content_path);
    DCHECK(content_path.IsAbsolute());
    file_path = content_path.Append(file_path);
  }

  std::string content;
  if (!base::ReadFileToString(file_path, &content)) {
    LOG(ERROR) << "Failed to load file " << file_path.value();
    return "";
  }
  return content;
}

const char* GetDemuxerStreamType(DemuxerStream* demuxer_stream) {
  return demuxer_stream->type() == DemuxerStream::AUDIO ? "audio" : "video";
}

void ReadDemuxerStream(DemuxerStream* demuxer_stream);

void OnDemuxerStreamRead(DemuxerStream* demuxer_stream,
                         DemuxerStream::Status status,
                         scoped_refptr<::media::DecoderBuffer> decoder_buffer) {
  if (!decoder_buffer->end_of_stream()) {
    LOG(INFO) << "Reading " << GetDemuxerStreamType(demuxer_stream)
              << " buffer at " << decoder_buffer->timestamp();
    ReadDemuxerStream(demuxer_stream);
  } else {
    LOG(INFO) << "Received " << GetDemuxerStreamType(demuxer_stream) << " EOS";
  }
}

void ReadDemuxerStream(DemuxerStream* demuxer_stream) {
  DCHECK(demuxer_stream);
  demuxer_stream->Read(
      base::BindOnce(OnDemuxerStreamRead, base::Unretained(demuxer_stream)));
}

}  // namespace

int SandboxMain(int argc, char** argv) {
  if (argc != 3) {
    // Path should be in the form of
    //     "cobalt/demos/media-element-demo/dash-video-240p.mp4".
    LOG(ERROR) << "Usage: " << argv[0] << " <audio_path> <video_path>";
    return 1;
  }

  DecoderBufferAllocator decoder_buffer_allocator;
  ::media::MediaLog media_log;
  base::MessageLoop message_loop;
  // A one-per-process task scheduler is needed for usage of APIs in
  // base/post_task.h which will be used by some net APIs like
  // URLRequestContext;
  base::TaskScheduler::CreateAndStartWithDefaultParams("Cobalt TaskScheduler");
  DemuxerHostStub demuxer_host;
  std::unique_ptr<ChunkDemuxer> demuxer(
      new ChunkDemuxer(base::BindOnce(OnDemuxerOpen), base::Closure(),
                       base::Bind(OnEncryptedMediaInitData), &media_log));
  demuxer->Initialize(&demuxer_host, base::Bind(OnDemuxerStatus));

  ChunkDemuxer::Status status =
      demuxer->AddId("audio", "audio/mp4", "mp4a.40.2");
  DCHECK_EQ(status, ChunkDemuxer::kOk);

  int video_url_length = strlen(argv[2]);
  if (video_url_length > 5 &&
      strncmp(argv[2] + video_url_length - 5, ".webm", 5) == 0) {
    status = demuxer->AddId("video", "video/webm", "vp9");
  } else {
    status = demuxer->AddId("video", "video/mp4", "avc1.640028");
  }
  DCHECK_EQ(status, ChunkDemuxer::kOk);

  base::TimeDelta timestamp_offset;

  std::string audio_content = LoadFile(argv[1]);
  std::string video_content = LoadFile(argv[2]);
  DCHECK(!audio_content.empty());
  DCHECK(!video_content.empty());

  demuxer->SetTracksWatcher("audio", base::Bind(OnInitSegmentReceived));
  demuxer->SetParseWarningCallback(
      "audio",
      base::BindRepeating([](::media::SourceBufferParseWarning warning) {
        LOG(WARNING) << "Encountered SourceBufferParseWarning "
                     << static_cast<int>(warning);
      }));
  demuxer->SetTracksWatcher("video", base::Bind(OnInitSegmentReceived));
  demuxer->SetParseWarningCallback(
      "video",
      base::BindRepeating([](::media::SourceBufferParseWarning warning) {
        LOG(WARNING) << "Encountered SourceBufferParseWarning "
                     << static_cast<int>(warning);
      }));
  bool result =
      demuxer->AppendData("audio", reinterpret_cast<uint8*>(&audio_content[0]),
                          audio_content.size(), base::TimeDelta(),
                          base::TimeDelta::Max(), &timestamp_offset);
  DCHECK(result);
  result =
      demuxer->AppendData("video", reinterpret_cast<uint8*>(&video_content[0]),
                          video_content.size(), base::TimeDelta(),
                          base::TimeDelta::Max(), &timestamp_offset);
  DCHECK(result);
  demuxer->MarkEndOfStream(::media::PIPELINE_OK);

  auto streams = demuxer->GetAllStreams();
  DemuxerStream* audio_stream = nullptr;
  DemuxerStream* video_stream = nullptr;
  for (auto&& stream : streams) {
    if (stream->type() == DemuxerStream::AUDIO) {
      DCHECK(!audio_stream);
      audio_stream = stream;
    } else if (stream->type() == DemuxerStream::VIDEO) {
      DCHECK(!video_stream);
      video_stream = stream;
    }
  }

  ReadDemuxerStream(audio_stream);
  ReadDemuxerStream(video_stream);

  base::RunLoop().RunUntilIdle();

  demuxer->Stop();

  return 0;
}

}  // namespace sandbox
}  // namespace media
}  // namespace cobalt

COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
