/*
 *  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 "modules/desktop_capture/desktop_frame_generator.h"

#include <cstdint>
#include <cstring>
#include <memory>

#include "modules/desktop_capture/desktop_frame.h"
#include "modules/desktop_capture/desktop_geometry.h"
#include "modules/desktop_capture/desktop_region.h"
#include "modules/desktop_capture/rgba_color.h"
#include "modules/desktop_capture/shared_memory.h"
#include "rtc_base/checks.h"
#include "rtc_base/random.h"
#include "rtc_base/time_utils.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(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, RgbaColor rgba_color) {
  static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t),
                "kBytesPerPixel should be 4.");
  RTC_DCHECK_GE(frame->size().width(), rect.right());
  RTC_DCHECK_GE(frame->size().height(), rect.bottom());
  // TODO(bugs.webrtc.org/436974448): Support other pixel formats.
  RTC_CHECK_EQ(FOURCC_ARGB, frame->pixel_format());
  uint32_t color = rgba_color.ToUInt32();
  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,
                 RgbaColor rgba_color) {
  region->IntersectWith(DesktopRect::MakeSize(frame->size()));
  for (DesktopRegion::Iterator it(*region); !it.IsAtEnd(); it.Advance()) {
    PaintRect(frame, it.rect(), rgba_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_, FOURCC_ARGB, factory)
                    .release()
              : new BasicDesktopFrame(size_, FOURCC_ARGB));
  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_, RgbaColor(0xFFFFFFFF));
  updated_region_.Swap(updated_region);
  return true;
}

}  // namespace webrtc
