/*
 *  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/modules/desktop_capture/rgba_color.h"
#include "webrtc/rtc_base/random.h"
#include "webrtc/rtc_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, 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());
  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_, 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_, RgbaColor(0xFFFFFFFF));
  updated_region_.Swap(updated_region);
  return true;
}

}  // namespace webrtc
