/*
 *  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.encoder_settings.payload_name = "VP8";
      send_config.encoder_settings.payload_type = kVideoPayloadType;
      VideoEncoderConfig encoder_config;
      test::FillEncoderConfiguration(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.encoder_settings);
      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, 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
