// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/overlay_info/qr_code_overlay.h"

#include <algorithm>
#include <string>

#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/overlay_info/overlay_info_registry.h"
#include "cobalt/render_tree/animations/animate_node.h"
#include "starboard/memory.h"
#include "third_party/QR-Code-generator/cpp/QrCode.hpp"

namespace cobalt {
namespace overlay_info {

namespace {

using qrcodegen::QrCode;
using render_tree::Image;
using render_tree::ImageNode;
using render_tree::ResourceProvider;

const int kMinimumQrCodeVersion = 3;
const int kPixelSizeInBytes = 4;
#if SB_IS_BIG_ENDIAN
const uint32_t kBlack = 0x000000FF;
#else   // SB_IS_BIG_ENDIAN
const uint32_t kBlack = 0xFF000000;
#endif  // SB_IS_BIG_ENDIAN
const uint32_t kWhite = 0xFFFFFFFF;
const uint32_t kBorderColor = kWhite;
const int kScreenMarginInPixels = 64;

uint32_t s_frame_index_ = 0;

void DrawRect(int width, int height, int pitch_in_bytes, uint32_t color,
              uint8_t* target_buffer) {
  while (height > 0) {
    uint32_t* pixels = reinterpret_cast<uint32_t*>(target_buffer);
    for (int i = 0; i < width; ++i) {
      pixels[i] = color;
    }
    target_buffer += pitch_in_bytes;
    --height;
  }
}

void DrawQrCode(const QrCode& qr_code, int module_dimension_in_pixels,
                int pitch_in_bytes, uint8_t* target_buffer) {
  uint8_t* row_data = target_buffer;
  for (int row = 0; row < qr_code.getSize(); ++row) {
    uint8_t* column_data = row_data;
    for (int column = 0; column < qr_code.getSize(); ++column) {
      DrawRect(module_dimension_in_pixels, module_dimension_in_pixels,
               pitch_in_bytes, qr_code.getModule(row, column) ? kBlack : kWhite,
               column_data);
      column_data += kPixelSizeInBytes * module_dimension_in_pixels;
    }

    row_data += pitch_in_bytes * module_dimension_in_pixels;
  }
}

scoped_refptr<Image> CreateImageForQrCode(const QrCode& qr_code,
                                          const math::Size& screen_size,
                                          int slots,
                                          ResourceProvider* resource_provider) {
  TRACE_EVENT0("cobalt::overlay_info", "CreateImageForQrCode()");

  const int module_dimension_in_pixels = screen_size.height() > 1080 ? 16 : 8;
  const int code_border_in_pixels = module_dimension_in_pixels * 2;

  int qr_code_size_in_blocks = qr_code.getSize();

  int column = (screen_size.width() - kScreenMarginInPixels * 2 -
                code_border_in_pixels) /
               (qr_code_size_in_blocks * module_dimension_in_pixels +
                code_border_in_pixels);
  column = std::min(column, slots);
  int row = (slots + column - 1) / column;

  int image_width =
      column * qr_code_size_in_blocks * module_dimension_in_pixels +
      code_border_in_pixels * (column + 1);
  int image_height = row * qr_code_size_in_blocks * module_dimension_in_pixels +
                     code_border_in_pixels * (row + 1);

  auto image_data = resource_provider->AllocateImageData(
      math::Size(image_width, image_height), render_tree::kPixelFormatRGBA8,
      render_tree::kAlphaFormatOpaque);
  DCHECK(image_data);
  auto image_desc = image_data->GetDescriptor();

  uint32_t slot_index = 0;
  auto row_data = image_data->GetMemory();
  for (int i = 0; i < row; ++i) {
    // Draw the top border of all qr code blocks in the row.
    DrawRect(image_width, code_border_in_pixels, image_desc.pitch_in_bytes,
             kBorderColor, row_data);
    row_data += code_border_in_pixels * image_desc.pitch_in_bytes;
    auto column_data = row_data;

    for (int j = 0; j < column; ++j) {
      // Draw the left border.
      DrawRect(code_border_in_pixels,
               qr_code_size_in_blocks * module_dimension_in_pixels,
               image_desc.pitch_in_bytes, kBorderColor, column_data);
      column_data += code_border_in_pixels * kPixelSizeInBytes;
      if (slot_index == s_frame_index_ % slots) {
        // Draw qr code.
        DrawQrCode(qr_code, module_dimension_in_pixels,
                   image_desc.pitch_in_bytes, column_data);
      } else {
        DrawRect(qr_code_size_in_blocks * module_dimension_in_pixels,
                 qr_code_size_in_blocks * module_dimension_in_pixels,
                 image_desc.pitch_in_bytes, kBlack, column_data);
      }
      ++slot_index;
      column_data += qr_code_size_in_blocks * module_dimension_in_pixels *
                     kPixelSizeInBytes;
    }

    // Draw the right border of the row.
    DrawRect(code_border_in_pixels,
             qr_code_size_in_blocks * module_dimension_in_pixels,
             image_desc.pitch_in_bytes, kBorderColor, column_data);

    row_data += qr_code_size_in_blocks * module_dimension_in_pixels *
                image_desc.pitch_in_bytes;
  }

  // Draw the bottom border of all qr code.
  DrawRect(image_width, code_border_in_pixels, image_desc.pitch_in_bytes,
           kBorderColor, row_data);

  return resource_provider->CreateImage(std::move(image_data));
}

void AnimateCB(math::Size screen_size, int slots,
               ResourceProvider* resource_provider,
               ImageNode::Builder* image_node, base::TimeDelta time) {
  SB_UNREFERENCED_PARAMETER(time);
  DCHECK(image_node);

  TRACE_EVENT0("cobalt::overlay_info", "AnimateCB()");

  OverlayInfoRegistry::Register("frame", s_frame_index_);
  ++s_frame_index_;

  std::string infos;
  OverlayInfoRegistry::RetrieveAndClear(&infos);

  if (infos.empty()) {
    image_node->source = NULL;
    return;
  }

  auto qrcode = QrCode::encodeText(infos.c_str(), QrCode::Ecc::LOW,
                                   kMinimumQrCodeVersion);
  image_node->source =
      CreateImageForQrCode(qrcode, screen_size, slots, resource_provider);
  auto image_size = image_node->source->GetSize();
  image_node->destination_rect = math::RectF(
      screen_size.width() - image_size.width() - kScreenMarginInPixels,
      screen_size.height() - image_size.height() - kScreenMarginInPixels,
      image_size.width(), image_size.height());
}

}  // namespace

QrCodeOverlay::QrCodeOverlay(
    const math::Size& screen_size, int slots,
    ResourceProvider* resource_provider,
    const RenderTreeProducedCB& render_tree_produced_cb)
    : render_tree_produced_cb_(render_tree_produced_cb),
      slots_(slots),
      screen_size_(screen_size),
      resource_provider_(resource_provider) {
  DCHECK_GT(screen_size.width(), 0);
  DCHECK_GT(screen_size.height(), 0);
  DCHECK(!render_tree_produced_cb_.is_null());

  UpdateRenderTree();
}

void QrCodeOverlay::SetSize(const math::Size& size) {
  DCHECK_GT(size.width(), 0);
  DCHECK_GT(size.height(), 0);

  screen_size_ = size;
  UpdateRenderTree();
}

void QrCodeOverlay::SetResourceProvider(ResourceProvider* resource_provider) {
  resource_provider_ = resource_provider;
  UpdateRenderTree();
}

void QrCodeOverlay::UpdateRenderTree() {
  TRACE_EVENT0("cobalt::overlay_info", "QrCodeOverlay::UpdateRenderTree()");

  if (resource_provider_ == NULL) {
    return;
  }

  scoped_refptr<ImageNode> image_node = new ImageNode(nullptr);
  render_tree::animations::AnimateNode::Builder animate_node_builder;

  animate_node_builder.Add(image_node, base::Bind(AnimateCB, screen_size_,
                                                  slots_, resource_provider_));

  render_tree_produced_cb_.Run(new render_tree::animations::AnimateNode(
      animate_node_builder, image_node));
}

}  // namespace overlay_info
}  // namespace cobalt
