/*
 *  Copyright (c) 2014 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 WEBRTC_VIDEO_RAMPUP_TESTS_H_
#define WEBRTC_VIDEO_RAMPUP_TESTS_H_

#include <map>
#include <string>
#include <vector>

#include "webrtc/base/scoped_ptr.h"
#include "webrtc/call.h"
#include "webrtc/call/transport_adapter.h"
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/test/call_test.h"

namespace webrtc {

static const int kTransmissionTimeOffsetExtensionId = 6;
static const int kAbsSendTimeExtensionId = 7;
static const int kTransportSequenceNumberExtensionId = 8;
static const unsigned int kSingleStreamTargetBps = 1000000;

class Clock;
class PacketRouter;
class ReceiveStatistics;
class RtpHeaderParser;
class RTPPayloadRegistry;
class RtpRtcp;

class StreamObserver : public newapi::Transport, public RemoteBitrateObserver {
 public:
  typedef std::map<uint32_t, int> BytesSentMap;
  typedef std::map<uint32_t, uint32_t> SsrcMap;
  StreamObserver(const SsrcMap& rtx_media_ssrcs,
                 newapi::Transport* feedback_transport,
                 Clock* clock);
  virtual ~StreamObserver();

  void set_expected_bitrate_bps(unsigned int expected_bitrate_bps);

  void set_start_bitrate_bps(unsigned int start_bitrate_bps);

  void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
                               unsigned int bitrate) override;

  bool SendRtp(const uint8_t* packet, size_t length) override;

  bool SendRtcp(const uint8_t* packet, size_t length) override;

  EventTypeWrapper Wait();

  void SetRemoteBitrateEstimator(RemoteBitrateEstimator* rbe);

  PacketRouter* GetPacketRouter();

 private:
  void ReportResult(const std::string& measurement,
                    size_t value,
                    const std::string& units);
  void TriggerTestDone() EXCLUSIVE_LOCKS_REQUIRED(crit_);

  Clock* const clock_;
  const rtc::scoped_ptr<EventWrapper> test_done_;
  const rtc::scoped_ptr<RtpHeaderParser> rtp_parser_;
  rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
  rtc::scoped_ptr<PacketRouter> packet_router_;
  internal::TransportAdapter feedback_transport_;
  const rtc::scoped_ptr<ReceiveStatistics> receive_stats_;
  const rtc::scoped_ptr<RTPPayloadRegistry> payload_registry_;
  rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;

  rtc::CriticalSection crit_;
  unsigned int expected_bitrate_bps_ GUARDED_BY(crit_);
  unsigned int start_bitrate_bps_ GUARDED_BY(crit_);
  SsrcMap rtx_media_ssrcs_ GUARDED_BY(crit_);
  size_t total_sent_ GUARDED_BY(crit_);
  size_t padding_sent_ GUARDED_BY(crit_);
  size_t rtx_media_sent_ GUARDED_BY(crit_);
  int total_packets_sent_ GUARDED_BY(crit_);
  int padding_packets_sent_ GUARDED_BY(crit_);
  int rtx_media_packets_sent_ GUARDED_BY(crit_);
  int64_t test_start_ms_ GUARDED_BY(crit_);
  int64_t ramp_up_finished_ms_ GUARDED_BY(crit_);
};

class LowRateStreamObserver : public test::DirectTransport,
                              public RemoteBitrateObserver,
                              public PacketReceiver {
 public:
  LowRateStreamObserver(newapi::Transport* feedback_transport,
                        Clock* clock,
                        size_t number_of_streams,
                        bool rtx_used);

  virtual void SetSendStream(VideoSendStream* send_stream);

  virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
                                       unsigned int bitrate);

  bool SendRtp(const uint8_t* data, size_t length) override;

  DeliveryStatus DeliverPacket(MediaType media_type,
                               const uint8_t* packet,
                               size_t length,
                               const PacketTime& packet_time) override;

  bool SendRtcp(const uint8_t* packet, size_t length) override;

  // Produces a string similar to "1stream_nortx", depending on the values of
  // number_of_streams_ and rtx_used_;
  std::string GetModifierString();

  // This method defines the state machine for the ramp up-down-up test.
  void EvolveTestState(unsigned int bitrate_bps);

  EventTypeWrapper Wait();

 private:
  static const unsigned int kHighBandwidthLimitBps = 80000;
  static const unsigned int kExpectedHighBitrateBps = 60000;
  static const unsigned int kLowBandwidthLimitBps = 20000;
  static const unsigned int kExpectedLowBitrateBps = 20000;
  enum TestStates { kFirstRampup, kLowRate, kSecondRampup };

  Clock* const clock_;
  const size_t number_of_streams_;
  const bool rtx_used_;
  const rtc::scoped_ptr<EventWrapper> test_done_;
  const rtc::scoped_ptr<RtpHeaderParser> rtp_parser_;
  const rtc::scoped_ptr<RTPPayloadRegistry> payload_registry_;
  rtc::scoped_ptr<RtpRtcp> rtp_rtcp_;
  internal::TransportAdapter feedback_transport_;
  const rtc::scoped_ptr<ReceiveStatistics> receive_stats_;
  rtc::scoped_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;

  rtc::CriticalSection crit_;
  VideoSendStream* send_stream_ GUARDED_BY(crit_);
  FakeNetworkPipe::Config forward_transport_config_ GUARDED_BY(crit_);
  TestStates test_state_ GUARDED_BY(crit_);
  int64_t state_start_ms_ GUARDED_BY(crit_);
  int64_t interval_start_ms_ GUARDED_BY(crit_);
  unsigned int last_remb_bps_ GUARDED_BY(crit_);
  size_t sent_bytes_ GUARDED_BY(crit_);
  size_t total_overuse_bytes_ GUARDED_BY(crit_);
  bool suspended_in_stats_ GUARDED_BY(crit_);
};

class RampUpTest : public test::CallTest {
 protected:
  void RunRampUpTest(size_t num_streams,
                     unsigned int start_bitrate_bps,
                     const std::string& extension_type,
                     bool rtx,
                     bool red);

  void RunRampUpDownUpTest(size_t number_of_streams, bool rtx, bool red);
};
}  // namespace webrtc
#endif  // WEBRTC_VIDEO_RAMPUP_TESTS_H_
