/*
 *  Copyright (c) 2019 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.
 */
#ifndef TEST_PEER_SCENARIO_PEER_SCENARIO_H_
#define TEST_PEER_SCENARIO_PEER_SCENARIO_H_

// The peer connection scenario test framework enables writing end to end unit
// tests on the peer connection level. It's similar to the Scenario test but
// uses the full stack, including SDP and ICE negotiation. This ensures that
// features work end to end. It's also diffferent from the other tests on peer
// connection level in that it does not rely on any mocks or fakes other than
// for media input and networking. Additionally it provides direct access to the
// underlying peer connection class.

#include <list>
#include <vector>

#include "test/network/network_emulation_manager.h"
#include "test/peer_scenario/peer_scenario_client.h"
#include "test/peer_scenario/signaling_route.h"
#include "test/scenario/stats_collection.h"
#include "test/scenario/video_frame_matcher.h"

namespace webrtc {
namespace test {

// The PeerScenario class represents a PeerConnection simulation scenario. The
// main purpose is to maintain ownership and ensure safe destruction order of
// clients and network emulation. Additionally it reduces the amount of bolier
// plate requited for some actions. For example usage see the existing tests
// using this class. Note that it should be used from a single calling thread.
// This thread will also be assigned as the signaling thread for all peer
// connections that are created. This means that the process methods must be
// used when waiting to ensure that messages are processed on the signaling
// thread.
class PeerScenario {
 public:
  PeerScenario();
  NetworkEmulationManagerImpl* net() { return &net_; }
  rtc::Thread* thread() { return signaling_thread_; }

  // Creates a client wrapping a peer connection conforming to the given config.
  // The client  will share the signaling thread with the scenario. To maintain
  // control of destruction order, ownership is kept within the scenario.
  PeerScenarioClient* CreateClient(PeerScenarioClient::Config config);

  // Sets up a signaling route that can be used for SDP and ICE.
  SignalingRoute ConnectSignaling(PeerScenarioClient* caller,
                                  PeerScenarioClient* callee,
                                  std::vector<EmulatedNetworkNode*> send_link,
                                  std::vector<EmulatedNetworkNode*> ret_link);

  // Connects two clients over given links. This will also start ICE signaling
  // and SDP negotiation with default behavior. For customized behavior,
  // ConnectSignaling should be used to allow more detailed control, for
  // instance to allow different signaling and media routes.
  void SimpleConnection(PeerScenarioClient* caller,
                        PeerScenarioClient* callee,
                        std::vector<EmulatedNetworkNode*> send_link,
                        std::vector<EmulatedNetworkNode*> ret_link);

  // Starts feeding the results of comparing captured frames from |send_track|
  // with decoded frames on |receiver| to |analyzer|.
  // TODO(srte): Provide a way to detach to allow removal of tracks.
  void AttachVideoQualityAnalyzer(VideoQualityAnalyzer* analyzer,
                                  VideoTrackInterface* send_track,
                                  PeerScenarioClient* receiver);

  // Waits on |event| while processing messages on the signaling thread.
  bool WaitAndProcess(rtc::Event* event,
                      TimeDelta max_duration = TimeDelta::seconds(5));

  // Process messages on the signaling thread for the given duration.
  void ProcessMessages(TimeDelta duration);

 private:
  // Helper struct to maintain ownership of the matcher and taps.
  struct PeerVideoQualityPair {
   public:
    PeerVideoQualityPair(Clock* capture_clock, VideoQualityAnalyzer* analyzer)
        : matcher_({analyzer->Handler()}),
          capture_tap_(capture_clock, &matcher_),
          decode_tap_(capture_clock, &matcher_, 0) {}
    VideoFrameMatcher matcher_;
    CapturedFrameTap capture_tap_;
    DecodedFrameTap decode_tap_;
  };
  Clock* clock() { return Clock::GetRealTimeClock(); }

  rtc::Thread* const signaling_thread_;
  std::list<PeerVideoQualityPair> video_quality_pairs_;
  NetworkEmulationManagerImpl net_;
  std::list<PeerScenarioClient> peer_clients_;
};

}  // namespace test
}  // namespace webrtc
#endif  // TEST_PEER_SCENARIO_PEER_SCENARIO_H_
