/*
 *  Copyright (c) 2017 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 "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h"

#include <memory>
#include <utility>

#include "modules/desktop_capture/desktop_capturer.h"
#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/desktop_frame_generator.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "modules/desktop_capture/desktop_region.h"
#include "modules/desktop_capture/fake_desktop_capturer.h"
#include "test/gtest.h"

namespace webrtc {

class BlankDetectorDesktopCapturerWrapperTest
    : public testing::Test,
      public DesktopCapturer::Callback {
 public:
  BlankDetectorDesktopCapturerWrapperTest();
  ~BlankDetectorDesktopCapturerWrapperTest() override;

 protected:
  void PerfTest(DesktopCapturer* capturer);

  const int frame_width_ = 1024;
  const int frame_height_ = 768;
  std::unique_ptr<BlankDetectorDesktopCapturerWrapper> wrapper_;
  DesktopCapturer* capturer_ = nullptr;
  BlackWhiteDesktopFramePainter painter_;
  int num_frames_captured_ = 0;
  DesktopCapturer::Result last_result_ = DesktopCapturer::Result::SUCCESS;
  std::unique_ptr<DesktopFrame> last_frame_;

 private:
  // DesktopCapturer::Callback interface.
  void OnCaptureResult(DesktopCapturer::Result result,
                       std::unique_ptr<DesktopFrame> frame) override;

  PainterDesktopFrameGenerator frame_generator_;
};

BlankDetectorDesktopCapturerWrapperTest::
    BlankDetectorDesktopCapturerWrapperTest() {
  frame_generator_.size()->set(frame_width_, frame_height_);
  frame_generator_.set_desktop_frame_painter(&painter_);
  std::unique_ptr<DesktopCapturer> capturer(new FakeDesktopCapturer());
  FakeDesktopCapturer* fake_capturer =
      static_cast<FakeDesktopCapturer*>(capturer.get());
  fake_capturer->set_frame_generator(&frame_generator_);
  capturer_ = fake_capturer;
  wrapper_.reset(new BlankDetectorDesktopCapturerWrapper(
      std::move(capturer), RgbaColor(0, 0, 0, 0)));
  wrapper_->Start(this);
}

BlankDetectorDesktopCapturerWrapperTest::
    ~BlankDetectorDesktopCapturerWrapperTest() = default;

void BlankDetectorDesktopCapturerWrapperTest::OnCaptureResult(
    DesktopCapturer::Result result,
    std::unique_ptr<DesktopFrame> frame) {
  last_result_ = result;
  last_frame_ = std::move(frame);
  num_frames_captured_++;
}

void BlankDetectorDesktopCapturerWrapperTest::PerfTest(
    DesktopCapturer* capturer) {
  for (int i = 0; i < 10000; i++) {
    capturer->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, i + 1);
  }
}

TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldDetectBlankFrame) {
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 1);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
  ASSERT_FALSE(last_frame_);
}

TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldPassBlankDetection) {
  painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(0, 0, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 1);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);

  painter_.updated_region()->AddRect(
      DesktopRect::MakeXYWH(frame_width_ - 100, frame_height_ - 100, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 2);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);

  painter_.updated_region()->AddRect(
      DesktopRect::MakeXYWH(0, frame_height_ - 100, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 3);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);

  painter_.updated_region()->AddRect(
      DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 4);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);

  painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(
      (frame_width_ >> 1) - 50, (frame_height_ >> 1) - 50, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 5);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);
}

TEST_F(BlankDetectorDesktopCapturerWrapperTest,
       ShouldNotCheckAfterANonBlankFrameReceived) {
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 1);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
  ASSERT_FALSE(last_frame_);

  painter_.updated_region()->AddRect(
      DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
  wrapper_->CaptureFrame();
  ASSERT_EQ(num_frames_captured_, 2);
  ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
  ASSERT_TRUE(last_frame_);

  for (int i = 0; i < 100; i++) {
    wrapper_->CaptureFrame();
    ASSERT_EQ(num_frames_captured_, i + 3);
    ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
    ASSERT_TRUE(last_frame_);
  }
}

// There is no perceptible impact by using BlankDetectorDesktopCapturerWrapper.
// i.e. less than 0.2ms per frame.
// [ OK ] DISABLED_Performance (10210 ms)
// [ OK ] DISABLED_PerformanceComparison (8791 ms)
TEST_F(BlankDetectorDesktopCapturerWrapperTest, DISABLED_Performance) {
  PerfTest(wrapper_.get());
}

TEST_F(BlankDetectorDesktopCapturerWrapperTest,
       DISABLED_PerformanceComparison) {
  capturer_->Start(this);
  PerfTest(capturer_);
}

}  // namespace webrtc
