/*
 *  Copyright (c) 2010 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_MEDIA_ENGINE_FAKEWEBRTCVIDEOENGINE_H_
#define WEBRTC_MEDIA_ENGINE_FAKEWEBRTCVIDEOENGINE_H_

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

#include "webrtc/api/video_codecs/video_decoder.h"
#include "webrtc/api/video_codecs/video_encoder.h"
#include "webrtc/media/base/codec.h"
#include "webrtc/media/engine/webrtcvideodecoderfactory.h"
#include "webrtc/media/engine/webrtcvideoencoderfactory.h"
#include "webrtc/modules/video_coding/include/video_error_codes.h"
#include "webrtc/rtc_base/basictypes.h"
#include "webrtc/rtc_base/criticalsection.h"
#include "webrtc/rtc_base/gunit.h"
#include "webrtc/rtc_base/stringutils.h"
#include "webrtc/rtc_base/thread_annotations.h"

namespace cricket {
static const int kEventTimeoutMs = 10000;

// Fake class for mocking out webrtc::VideoDecoder
class FakeWebRtcVideoDecoder : public webrtc::VideoDecoder {
 public:
  FakeWebRtcVideoDecoder() : num_frames_received_(0) {}

  virtual int32_t InitDecode(const webrtc::VideoCodec*, int32_t) {
    return WEBRTC_VIDEO_CODEC_OK;
  }

  virtual int32_t Decode(const webrtc::EncodedImage&,
                         bool,
                         const webrtc::RTPFragmentationHeader*,
                         const webrtc::CodecSpecificInfo*,
                         int64_t) {
    num_frames_received_++;
    return WEBRTC_VIDEO_CODEC_OK;
  }

  virtual int32_t RegisterDecodeCompleteCallback(
      webrtc::DecodedImageCallback*) {
    return WEBRTC_VIDEO_CODEC_OK;
  }

  virtual int32_t Release() { return WEBRTC_VIDEO_CODEC_OK; }

  int GetNumFramesReceived() const {
    return num_frames_received_;
  }

 private:
  int num_frames_received_;
};

// Fake class for mocking out WebRtcVideoDecoderFactory.
class FakeWebRtcVideoDecoderFactory : public WebRtcVideoDecoderFactory {
 public:
  FakeWebRtcVideoDecoderFactory()
      : num_created_decoders_(0) {
  }

  virtual webrtc::VideoDecoder* CreateVideoDecoder(
      webrtc::VideoCodecType type) {
    if (supported_codec_types_.count(type) == 0) {
      return NULL;
    }
    FakeWebRtcVideoDecoder* decoder = new FakeWebRtcVideoDecoder();
    decoders_.push_back(decoder);
    num_created_decoders_++;
    return decoder;
  }

  virtual webrtc::VideoDecoder* CreateVideoDecoderWithParams(
      webrtc::VideoCodecType type,
      VideoDecoderParams params) {
    params_.push_back(params);
    return CreateVideoDecoder(type);
  }

  virtual void DestroyVideoDecoder(webrtc::VideoDecoder* decoder) {
    decoders_.erase(
        std::remove(decoders_.begin(), decoders_.end(), decoder),
        decoders_.end());
    delete decoder;
  }

  void AddSupportedVideoCodecType(webrtc::VideoCodecType type) {
    supported_codec_types_.insert(type);
  }

  int GetNumCreatedDecoders() {
    return num_created_decoders_;
  }

  const std::vector<FakeWebRtcVideoDecoder*>& decoders() {
    return decoders_;
  }

  const std::vector<VideoDecoderParams>& params() { return params_; }

 private:
  std::set<webrtc::VideoCodecType> supported_codec_types_;
  std::vector<FakeWebRtcVideoDecoder*> decoders_;
  int num_created_decoders_;
  std::vector<VideoDecoderParams> params_;
};

// Fake class for mocking out webrtc::VideoEnoder
class FakeWebRtcVideoEncoder : public webrtc::VideoEncoder {
 public:
  FakeWebRtcVideoEncoder()
      : init_encode_event_(false, false), num_frames_encoded_(0) {}

  int32_t InitEncode(const webrtc::VideoCodec* codecSettings,
                     int32_t numberOfCores,
                     size_t maxPayloadSize) override {
    rtc::CritScope lock(&crit_);
    codec_settings_ = *codecSettings;
    init_encode_event_.Set();
    return WEBRTC_VIDEO_CODEC_OK;
  }

  bool WaitForInitEncode() { return init_encode_event_.Wait(kEventTimeoutMs); }

  webrtc::VideoCodec GetCodecSettings() {
    rtc::CritScope lock(&crit_);
    return codec_settings_;
  }

  int32_t Encode(const webrtc::VideoFrame& inputImage,
                 const webrtc::CodecSpecificInfo* codecSpecificInfo,
                 const std::vector<webrtc::FrameType>* frame_types) override {
    rtc::CritScope lock(&crit_);
    ++num_frames_encoded_;
    init_encode_event_.Set();
    return WEBRTC_VIDEO_CODEC_OK;
  }

  int32_t RegisterEncodeCompleteCallback(
      webrtc::EncodedImageCallback* callback) override {
    return WEBRTC_VIDEO_CODEC_OK;
  }

  int32_t Release() override { return WEBRTC_VIDEO_CODEC_OK; }

  int32_t SetChannelParameters(uint32_t packetLoss, int64_t rtt) override {
    return WEBRTC_VIDEO_CODEC_OK;
  }

  int32_t SetRateAllocation(const webrtc::BitrateAllocation& allocation,
                            uint32_t framerate) override {
    return WEBRTC_VIDEO_CODEC_OK;
  }

  int GetNumEncodedFrames() {
    rtc::CritScope lock(&crit_);
    return num_frames_encoded_;
  }

 private:
  rtc::CriticalSection crit_;
  rtc::Event init_encode_event_;
  int num_frames_encoded_ RTC_GUARDED_BY(crit_);
  webrtc::VideoCodec codec_settings_ RTC_GUARDED_BY(crit_);
};

// Fake class for mocking out WebRtcVideoEncoderFactory.
class FakeWebRtcVideoEncoderFactory : public WebRtcVideoEncoderFactory {
 public:
  FakeWebRtcVideoEncoderFactory()
      : created_video_encoder_event_(false, false),
        num_created_encoders_(0),
        encoders_have_internal_sources_(false) {}

  webrtc::VideoEncoder* CreateVideoEncoder(
      const cricket::VideoCodec& codec) override {
    rtc::CritScope lock(&crit_);
    if (!FindMatchingCodec(codecs_, codec))
      return nullptr;
    FakeWebRtcVideoEncoder* encoder = new FakeWebRtcVideoEncoder();
    encoders_.push_back(encoder);
    num_created_encoders_++;
    created_video_encoder_event_.Set();
    return encoder;
  }

  bool WaitForCreatedVideoEncoders(int num_encoders) {
    int64_t start_offset_ms = rtc::TimeMillis();
    int64_t wait_time = kEventTimeoutMs;
    do {
      if (GetNumCreatedEncoders() >= num_encoders)
        return true;
      wait_time = kEventTimeoutMs - (rtc::TimeMillis() - start_offset_ms);
    } while (wait_time > 0 && created_video_encoder_event_.Wait(wait_time));
    return false;
  }

  void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override {
    rtc::CritScope lock(&crit_);
    encoders_.erase(
        std::remove(encoders_.begin(), encoders_.end(), encoder),
        encoders_.end());
    delete encoder;
  }

  const std::vector<cricket::VideoCodec>& supported_codecs() const override {
    return codecs_;
  }

  bool EncoderTypeHasInternalSource(
      webrtc::VideoCodecType type) const override {
    return encoders_have_internal_sources_;
  }

  void set_encoders_have_internal_sources(bool internal_source) {
    encoders_have_internal_sources_ = internal_source;
  }

  void AddSupportedVideoCodec(const cricket::VideoCodec& codec) {
    codecs_.push_back(codec);
  }

  void AddSupportedVideoCodecType(const std::string& name) {
    codecs_.push_back(cricket::VideoCodec(name));
  }

  int GetNumCreatedEncoders() {
    rtc::CritScope lock(&crit_);
    return num_created_encoders_;
  }

  const std::vector<FakeWebRtcVideoEncoder*> encoders() {
    rtc::CritScope lock(&crit_);
    return encoders_;
  }

 private:
  rtc::CriticalSection crit_;
  rtc::Event created_video_encoder_event_;
  std::vector<cricket::VideoCodec> codecs_;
  std::vector<FakeWebRtcVideoEncoder*> encoders_ RTC_GUARDED_BY(crit_);
  int num_created_encoders_ RTC_GUARDED_BY(crit_);
  bool encoders_have_internal_sources_;
};

}  // namespace cricket

#endif  // WEBRTC_MEDIA_ENGINE_FAKEWEBRTCVIDEOENGINE_H_
