/*
 *  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 "api/test/loopback_media_transport.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "test/gmock.h"

namespace webrtc {

namespace {

class MockMediaTransportAudioSinkInterface
    : public MediaTransportAudioSinkInterface {
 public:
  MOCK_METHOD(void,
              OnData,
              (uint64_t, MediaTransportEncodedAudioFrame),
              (override));
};

class MockMediaTransportVideoSinkInterface
    : public MediaTransportVideoSinkInterface {
 public:
  MOCK_METHOD(void,
              OnData,
              (uint64_t, MediaTransportEncodedVideoFrame),
              (override));
};

class MockMediaTransportKeyFrameRequestCallback
    : public MediaTransportKeyFrameRequestCallback {
 public:
  MOCK_METHOD(void, OnKeyFrameRequested, (uint64_t), (override));
};

class MockDataChannelSink : public DataChannelSink {
 public:
  MOCK_METHOD(void,
              OnDataReceived,
              (int, DataMessageType, const rtc::CopyOnWriteBuffer&),
              (override));
  MOCK_METHOD(void, OnChannelClosing, (int), (override));
  MOCK_METHOD(void, OnChannelClosed, (int), (override));
  MOCK_METHOD(void, OnReadyToSend, (), (override));
};

class MockStateCallback : public MediaTransportStateCallback {
 public:
  MOCK_METHOD(void, OnStateChanged, (MediaTransportState), (override));
};

}  // namespace

TEST(LoopbackMediaTransport, DataDeliveredToSink) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockDataChannelSink sink;
  transport_pair.first_datagram_transport()->SetDataSink(&sink);

  const int channel_id = 1;
  EXPECT_CALL(
      sink, OnDataReceived(
                channel_id, DataMessageType::kText,
                ::testing::Property<rtc::CopyOnWriteBuffer, const char*>(
                    &rtc::CopyOnWriteBuffer::cdata, ::testing::StrEq("foo"))));

  SendDataParams params;
  params.type = DataMessageType::kText;
  rtc::CopyOnWriteBuffer buffer("foo");
  transport_pair.second_datagram_transport()->SendData(channel_id, params,
                                                       buffer);

  transport_pair.FlushAsyncInvokes();
  transport_pair.first_datagram_transport()->SetDataSink(nullptr);
}

TEST(LoopbackMediaTransport, CloseDeliveredToSink) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockDataChannelSink first_sink;
  transport_pair.first_datagram_transport()->SetDataSink(&first_sink);

  MockDataChannelSink second_sink;
  transport_pair.second_datagram_transport()->SetDataSink(&second_sink);

  const int channel_id = 1;
  {
    ::testing::InSequence s;
    EXPECT_CALL(second_sink, OnChannelClosing(channel_id));
    EXPECT_CALL(second_sink, OnChannelClosed(channel_id));
    EXPECT_CALL(first_sink, OnChannelClosed(channel_id));
  }

  transport_pair.first_datagram_transport()->CloseChannel(channel_id);

  transport_pair.FlushAsyncInvokes();
  transport_pair.first_datagram_transport()->SetDataSink(nullptr);
  transport_pair.second_datagram_transport()->SetDataSink(nullptr);
}

TEST(LoopbackMediaTransport, InitialStateDeliveredWhenCallbackSet) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockStateCallback state_callback;
  EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));

  thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
    transport_pair.first_datagram_transport()->SetTransportStateCallback(
        &state_callback);
  });
  transport_pair.FlushAsyncInvokes();
}

TEST(LoopbackMediaTransport, ChangedStateDeliveredWhenCallbackSet) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  transport_pair.SetState(MediaTransportState::kWritable);
  transport_pair.FlushAsyncInvokes();

  MockStateCallback state_callback;

  EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
  thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
    transport_pair.first_datagram_transport()->SetTransportStateCallback(
        &state_callback);
  });
  transport_pair.FlushAsyncInvokes();
}

TEST(LoopbackMediaTransport, StateChangeDeliveredToCallback) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockStateCallback state_callback;

  EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kPending));
  EXPECT_CALL(state_callback, OnStateChanged(MediaTransportState::kWritable));
  thread->Invoke<void>(RTC_FROM_HERE, [&transport_pair, &state_callback] {
    transport_pair.first_datagram_transport()->SetTransportStateCallback(
        &state_callback);
  });
  transport_pair.SetState(MediaTransportState::kWritable);
  transport_pair.FlushAsyncInvokes();
}

TEST(LoopbackMediaTransport, NotReadyToSendWhenDataSinkSet) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockDataChannelSink data_channel_sink;
  EXPECT_CALL(data_channel_sink, OnReadyToSend()).Times(0);

  transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
  transport_pair.FlushAsyncInvokes();
  transport_pair.first_datagram_transport()->SetDataSink(nullptr);
}

TEST(LoopbackMediaTransport, ReadyToSendWhenDataSinkSet) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  transport_pair.SetState(MediaTransportState::kWritable);
  transport_pair.FlushAsyncInvokes();

  MockDataChannelSink data_channel_sink;
  EXPECT_CALL(data_channel_sink, OnReadyToSend());

  transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
  transport_pair.FlushAsyncInvokes();
  transport_pair.first_datagram_transport()->SetDataSink(nullptr);
}

TEST(LoopbackMediaTransport, StateChangeDeliveredToDataSink) {
  std::unique_ptr<rtc::Thread> thread = rtc::Thread::Create();
  thread->Start();
  MediaTransportPair transport_pair(thread.get());

  MockDataChannelSink data_channel_sink;
  EXPECT_CALL(data_channel_sink, OnReadyToSend());

  transport_pair.first_datagram_transport()->SetDataSink(&data_channel_sink);
  transport_pair.SetState(MediaTransportState::kWritable);
  transport_pair.FlushAsyncInvokes();
  transport_pair.first_datagram_transport()->SetDataSink(nullptr);
}

}  // namespace webrtc
