/*
 *  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_CLIENT_H_
#define TEST_PEER_SCENARIO_PEER_SCENARIO_CLIENT_H_

#include <functional>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "absl/memory/memory.h"
#include "api/peer_connection_interface.h"
#include "api/test/network_emulation_manager.h"
#include "api/test/time_controller.h"
#include "pc/test/frame_generator_capturer_video_track_source.h"
#include "test/logging/log_writer.h"

namespace webrtc {
namespace test {

// Wrapper for a PeerConnection for use in PeerScenario tests. It's intended to
// be a minimal wrapper for a peer connection that's simple to use in testing.
// In particular the constructor hides a lot of the required setup for a peer
// connection.
class PeerScenarioClient {
 public:
  struct CallbackHandlers {
    std::vector<std::function<void(PeerConnectionInterface::SignalingState)>>
        on_signaling_change;
    std::vector<std::function<void(rtc::scoped_refptr<DataChannelInterface>)>>
        on_data_channel;
    std::vector<std::function<void()>> on_renegotiation_needed;
    std::vector<
        std::function<void(PeerConnectionInterface::IceConnectionState)>>
        on_standardized_ice_connection_change;
    std::vector<
        std::function<void(PeerConnectionInterface::PeerConnectionState)>>
        on_connection_change;
    std::vector<std::function<void(PeerConnectionInterface::IceGatheringState)>>
        on_ice_gathering_change;
    std::vector<std::function<void(const IceCandidateInterface*)>>
        on_ice_candidate;
    std::vector<std::function<void(const std::string&,
                                   int,
                                   const std::string&,
                                   int,
                                   const std::string&)>>
        on_ice_candidate_error;
    std::vector<std::function<void(const std::vector<cricket::Candidate>&)>>
        on_ice_candidates_removed;
    std::vector<std::function<void(
        rtc::scoped_refptr<RtpReceiverInterface>,
        const std::vector<rtc::scoped_refptr<MediaStreamInterface>>&)>>
        on_add_track;
    std::vector<
        std::function<void(rtc::scoped_refptr<RtpTransceiverInterface>)>>
        on_track;
    std::vector<std::function<void(rtc::scoped_refptr<RtpReceiverInterface>)>>
        on_remove_track;
  };
  struct Config {
    // WebRTC only support one audio device that is setup up on construction, so
    // we provide the audio generator configuration here rather than on creation
    // of the tracks. This is unlike video, where multiple capture sources can
    // be used at the same time.
    struct AudioSource {
      int sample_rate = 48000;
      int channels = 1;
      struct PulsedNoise {
        double amplitude = 0.1;
      };
      absl::optional<PulsedNoise> pulsed_noise = PulsedNoise();
    } audio;
    // The created endpoints can be accessed using the map key as |index| in
    // PeerScenarioClient::endpoint(index).
    std::map<int, EmulatedEndpointConfig> endpoints = {
        {0, EmulatedEndpointConfig()}};
    CallbackHandlers handlers;
    PeerConnectionInterface::RTCConfiguration rtc_config;
    Config() { rtc_config.sdp_semantics = SdpSemantics::kUnifiedPlan; }
  };

  struct VideoSendTrackConfig {
    FrameGeneratorCapturerConfig generator;
    bool screencast = false;
  };

  struct AudioSendTrack {
    AudioTrackInterface* track;
    RtpSenderInterface* sender;
  };

  struct VideoSendTrack {
    FrameGeneratorCapturer* capturer;
    FrameGeneratorCapturerVideoTrackSource* source;
    VideoTrackInterface* track;
    RtpSenderInterface* sender;
  };

  PeerScenarioClient(
      NetworkEmulationManager* net,
      rtc::Thread* signaling_thread,
      std::unique_ptr<LogWriterFactoryInterface> log_writer_factory,
      Config config);

  PeerConnectionFactoryInterface* factory() { return pc_factory_.get(); }
  PeerConnectionInterface* pc() {
    RTC_DCHECK_RUN_ON(signaling_thread_);
    return peer_connection_.get();
  }
  rtc::Thread* thread() { return signaling_thread_; }
  Clock* clock() { return Clock::GetRealTimeClock(); }

  // Returns the endpoint created from the EmulatedEndpointConfig with the same
  // index in PeerScenarioClient::config.
  EmulatedEndpoint* endpoint(int index = 0);

  AudioSendTrack CreateAudio(std::string track_id,
                             cricket::AudioOptions options);
  VideoSendTrack CreateVideo(std::string track_id, VideoSendTrackConfig config);

  void AddVideoReceiveSink(std::string track_id,
                           rtc::VideoSinkInterface<VideoFrame>* video_sink);

  CallbackHandlers* handlers() { return &handlers_; }

  // Note that there's no provision for munging SDP as that is deprecated
  // behavior.
  void CreateAndSetSdp(std::function<void(std::string)> offer_handler);
  void SetSdpOfferAndGetAnswer(std::string remote_offer,
                               std::function<void(std::string)> answer_handler);
  void SetSdpAnswer(
      std::string remote_answer,
      std::function<void(const SessionDescriptionInterface& answer)>
          done_handler);

  // Adds the given ice candidate when the peer connection is ready.
  void AddIceCandidate(std::unique_ptr<IceCandidateInterface> candidate);

 private:
  const std::map<int, EmulatedEndpoint*> endpoints_;
  TaskQueueFactory* const task_queue_factory_;
  rtc::Thread* const signaling_thread_;
  const std::unique_ptr<LogWriterFactoryInterface> log_writer_factory_;
  const std::unique_ptr<rtc::Thread> worker_thread_;
  CallbackHandlers handlers_ RTC_GUARDED_BY(signaling_thread_);
  const std::unique_ptr<PeerConnectionObserver> observer_;
  std::map<std::string, std::vector<rtc::VideoSinkInterface<VideoFrame>*>>
      track_id_to_video_sinks_ RTC_GUARDED_BY(signaling_thread_);
  std::list<std::unique_ptr<IceCandidateInterface>> pending_ice_candidates_
      RTC_GUARDED_BY(signaling_thread_);

  rtc::scoped_refptr<PeerConnectionFactoryInterface> pc_factory_;
  rtc::scoped_refptr<PeerConnectionInterface> peer_connection_
      RTC_GUARDED_BY(signaling_thread_);
};

}  // namespace test
}  // namespace webrtc

#endif  // TEST_PEER_SCENARIO_PEER_SCENARIO_CLIENT_H_
