/*
 *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video/end_to_end_tests/multi_stream_tester.h"

#include <memory>
#include <utility>
#include <vector>

#include "logging/rtc_event_log/rtc_event_log.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "test/call_test.h"
#include "test/encoder_settings.h"

namespace webrtc {

MultiStreamTester::MultiStreamTester(
    test::SingleThreadedTaskQueueForTesting* task_queue)
    : task_queue_(task_queue) {
  // TODO(sprang): Cleanup when msvc supports explicit initializers for array.
  codec_settings[0] = {1, 640, 480};
  codec_settings[1] = {2, 320, 240};
  codec_settings[2] = {3, 240, 160};
  class multi_stream_test {
   public:
    multi_stream_test();
  };
}

MultiStreamTester::~MultiStreamTester() {}

void MultiStreamTester::RunTest() {
  webrtc::RtcEventLogNullImpl event_log;
  Call::Config config(&event_log);
  std::unique_ptr<Call> sender_call;
  std::unique_ptr<Call> receiver_call;
  std::unique_ptr<test::DirectTransport> sender_transport;
  std::unique_ptr<test::DirectTransport> receiver_transport;

  VideoSendStream* send_streams[kNumStreams];
  VideoReceiveStream* receive_streams[kNumStreams];
  test::FrameGeneratorCapturer* frame_generators[kNumStreams];
  std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders;
  std::unique_ptr<VideoEncoder> encoders[kNumStreams];

  task_queue_->SendTask([&]() {
    sender_call = rtc::WrapUnique(Call::Create(config));
    receiver_call = rtc::WrapUnique(Call::Create(config));
    sender_transport =
        rtc::WrapUnique(CreateSendTransport(task_queue_, sender_call.get()));
    receiver_transport = rtc::WrapUnique(
        CreateReceiveTransport(task_queue_, receiver_call.get()));

    sender_transport->SetReceiver(receiver_call->Receiver());
    receiver_transport->SetReceiver(sender_call->Receiver());

    for (size_t i = 0; i < kNumStreams; ++i)
      encoders[i] = VP8Encoder::Create();

    for (size_t i = 0; i < kNumStreams; ++i) {
      uint32_t ssrc = codec_settings[i].ssrc;
      int width = codec_settings[i].width;
      int height = codec_settings[i].height;

      VideoSendStream::Config send_config(sender_transport.get());
      send_config.rtp.ssrcs.push_back(ssrc);
      send_config.encoder_settings.encoder = encoders[i].get();
      send_config.rtp.payload_name = "VP8";
      send_config.rtp.payload_type = kVideoPayloadType;
      VideoEncoderConfig encoder_config;
      test::FillEncoderConfiguration(kVideoCodecVP8, 1, &encoder_config);
      encoder_config.max_bitrate_bps = 100000;

      UpdateSendConfig(i, &send_config, &encoder_config, &frame_generators[i]);

      send_streams[i] = sender_call->CreateVideoSendStream(
          send_config.Copy(), encoder_config.Copy());
      send_streams[i]->Start();

      VideoReceiveStream::Config receive_config(receiver_transport.get());
      receive_config.rtp.remote_ssrc = ssrc;
      receive_config.rtp.local_ssrc = test::CallTest::kReceiverLocalVideoSsrc;
      VideoReceiveStream::Decoder decoder =
          test::CreateMatchingDecoder(send_config);
      allocated_decoders.push_back(
          std::unique_ptr<VideoDecoder>(decoder.decoder));
      receive_config.decoders.push_back(decoder);

      UpdateReceiveConfig(i, &receive_config);

      receive_streams[i] =
          receiver_call->CreateVideoReceiveStream(std::move(receive_config));
      receive_streams[i]->Start();

      frame_generators[i] = test::FrameGeneratorCapturer::Create(
          width, height, rtc::nullopt, rtc::nullopt, 30,
          Clock::GetRealTimeClock());
      send_streams[i]->SetSource(
          frame_generators[i],
          VideoSendStream::DegradationPreference::kMaintainFramerate);
      frame_generators[i]->Start();
    }
  });

  Wait();

  task_queue_->SendTask([&]() {
    for (size_t i = 0; i < kNumStreams; ++i) {
      frame_generators[i]->Stop();
      sender_call->DestroyVideoSendStream(send_streams[i]);
      receiver_call->DestroyVideoReceiveStream(receive_streams[i]);
      delete frame_generators[i];
    }

    sender_transport.reset();
    receiver_transport.reset();

    sender_call.reset();
    receiver_call.reset();
  });
}

void MultiStreamTester::UpdateSendConfig(
    size_t stream_index,
    VideoSendStream::Config* send_config,
    VideoEncoderConfig* encoder_config,
    test::FrameGeneratorCapturer** frame_generator) {}

void MultiStreamTester::UpdateReceiveConfig(
    size_t stream_index,
    VideoReceiveStream::Config* receive_config) {}

test::DirectTransport* MultiStreamTester::CreateSendTransport(
    test::SingleThreadedTaskQueueForTesting* task_queue,
    Call* sender_call) {
  return new test::DirectTransport(task_queue, sender_call, payload_type_map_);
}

test::DirectTransport* MultiStreamTester::CreateReceiveTransport(
    test::SingleThreadedTaskQueueForTesting* task_queue,
    Call* receiver_call) {
  return new test::DirectTransport(task_queue, receiver_call,
                                   payload_type_map_);
}
}  // namespace webrtc
