/*
 *  Copyright (c) 2016 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 "webrtc/modules/desktop_capture/desktop_frame_generator.h"

#include <stdint.h>
#include <string.h>

#include <memory>

#include "webrtc/base/random.h"
#include "webrtc/base/timeutils.h"

namespace webrtc {

namespace {

// Sets |updated_region| to |frame|. If |enlarge_updated_region| is
// true, this function will randomly enlarge each DesktopRect in
// |updated_region|. But the enlarged DesktopRegion won't excceed the
// frame->size(). If |add_random_updated_region| is true, several random
// rectangles will also be included in |frame|.
void SetUpdatedRegion(DesktopFrame* frame,
                      const DesktopRegion& updated_region,
                      bool enlarge_updated_region,
                      int enlarge_range,
                      bool add_random_updated_region) {
  const DesktopRect screen_rect = DesktopRect::MakeSize(frame->size());
  Random random(rtc::TimeMicros());
  frame->mutable_updated_region()->Clear();
  for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd();
       it.Advance()) {
    DesktopRect rect = it.rect();
    if (enlarge_updated_region && enlarge_range > 0) {
      rect.Extend(random.Rand(enlarge_range), random.Rand(enlarge_range),
                  random.Rand(enlarge_range), random.Rand(enlarge_range));
      rect.IntersectWith(screen_rect);
    }
    frame->mutable_updated_region()->AddRect(rect);
  }

  if (add_random_updated_region) {
    for (int i = random.Rand(10); i >= 0; i--) {
      // At least a 1 x 1 updated region.
      const int left = random.Rand(0, frame->size().width() - 2);
      const int top = random.Rand(0, frame->size().height() - 2);
      const int right = random.Rand(left + 1, frame->size().width());
      const int bottom = random.Rand(top + 1, frame->size().height());
      frame->mutable_updated_region()->AddRect(
          DesktopRect::MakeLTRB(left, top, right, bottom));
    }
  }
}

// Paints pixels in |rect| of |frame| to |color|.
void PaintRect(DesktopFrame* frame, DesktopRect rect, uint32_t color) {
  static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t),
                "kBytesPerPixel should be 4.");
  RTC_DCHECK(frame->size().width() >= rect.right() &&
             frame->size().height() >= rect.bottom());
  uint8_t* row = frame->GetFrameDataAtPos(rect.top_left());
  for (int i = 0; i < rect.height(); i++) {
    uint32_t* column = reinterpret_cast<uint32_t*>(row);
    for (int j = 0; j < rect.width(); j++) {
      column[j] = color;
    }
    row += frame->stride();
  }
}

// Paints pixels in |region| of |frame| to |color|.
void PaintRegion(DesktopFrame* frame, DesktopRegion* region, uint32_t color) {
  region->IntersectWith(DesktopRect::MakeSize(frame->size()));
  for (DesktopRegion::Iterator it(*region); !it.IsAtEnd(); it.Advance()) {
    PaintRect(frame, it.rect(), color);
  }
}

}  // namespace

DesktopFrameGenerator::DesktopFrameGenerator() {}
DesktopFrameGenerator::~DesktopFrameGenerator() {}

DesktopFramePainter::DesktopFramePainter() {}
DesktopFramePainter::~DesktopFramePainter() {}

PainterDesktopFrameGenerator::PainterDesktopFrameGenerator()
    : size_(1024, 768),
      return_frame_(true),
      provide_updated_region_hints_(false),
      enlarge_updated_region_(false),
      enlarge_range_(20),
      add_random_updated_region_(false),
      painter_(nullptr) {}
PainterDesktopFrameGenerator::~PainterDesktopFrameGenerator() {}

std::unique_ptr<DesktopFrame> PainterDesktopFrameGenerator::GetNextFrame(
    SharedMemoryFactory* factory) {
  if (!return_frame_) {
    return nullptr;
  }

  std::unique_ptr<DesktopFrame> frame = std::unique_ptr<DesktopFrame>(
      factory ? SharedMemoryDesktopFrame::Create(size_, factory).release()
              : new BasicDesktopFrame(size_));
  if (painter_) {
    DesktopRegion updated_region;
    if (!painter_->Paint(frame.get(), &updated_region)) {
      return nullptr;
    }

    if (provide_updated_region_hints_) {
      SetUpdatedRegion(frame.get(), updated_region, enlarge_updated_region_,
                       enlarge_range_, add_random_updated_region_);
    } else {
      frame->mutable_updated_region()->SetRect(
          DesktopRect::MakeSize(frame->size()));
    }
  }

  return frame;
}

DesktopSize* PainterDesktopFrameGenerator::size() {
  return &size_;
}

void PainterDesktopFrameGenerator::set_return_frame(bool return_frame) {
  return_frame_ = return_frame;
}

void PainterDesktopFrameGenerator::set_provide_updated_region_hints(
    bool provide_updated_region_hints) {
  provide_updated_region_hints_ = provide_updated_region_hints;
}

void PainterDesktopFrameGenerator::set_enlarge_updated_region(
    bool enlarge_updated_region) {
  enlarge_updated_region_ = enlarge_updated_region;
}

void PainterDesktopFrameGenerator::set_enlarge_range(int enlarge_range) {
  enlarge_range_ = enlarge_range;
}

void PainterDesktopFrameGenerator::set_add_random_updated_region(
    bool add_random_updated_region) {
  add_random_updated_region_ = add_random_updated_region;
}

void PainterDesktopFrameGenerator::set_desktop_frame_painter(
    DesktopFramePainter* painter) {
  painter_ = painter;
}

BlackWhiteDesktopFramePainter::BlackWhiteDesktopFramePainter() {}
BlackWhiteDesktopFramePainter::~BlackWhiteDesktopFramePainter() {}

DesktopRegion* BlackWhiteDesktopFramePainter::updated_region() {
  return &updated_region_;
}

bool BlackWhiteDesktopFramePainter::Paint(DesktopFrame* frame,
                                          DesktopRegion* updated_region) {
  RTC_DCHECK(updated_region->is_empty());
  memset(frame->data(), 0, frame->stride() * frame->size().height());
  PaintRegion(frame, &updated_region_, UINT32_MAX);
  updated_region_.Swap(updated_region);
  return true;
}

}  // namespace webrtc
