// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "pdf/document_layout.h"

#include <algorithm>

#include "base/check_op.h"
#include "base/values.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"

namespace chrome_pdf {

namespace {

constexpr char kDirection[] = "direction";
constexpr char kDefaultPageOrientation[] = "defaultPageOrientation";
constexpr char kTwoUpViewEnabled[] = "twoUpViewEnabled";

int GetWidestPageWidth(const std::vector<gfx::Size>& page_sizes) {
  int widest_page_width = 0;
  for (const auto& page_size : page_sizes) {
    widest_page_width = std::max(widest_page_width, page_size.width());
  }

  return widest_page_width;
}

gfx::Rect InsetRect(const gfx::Rect& rect,
                    const draw_utils::PageInsetSizes& inset_sizes) {
  gfx::Rect inset_rect(rect);
  inset_rect.Inset(inset_sizes.left, inset_sizes.top, inset_sizes.right,
                   inset_sizes.bottom);
  return inset_rect;
}

}  // namespace

const draw_utils::PageInsetSizes DocumentLayout::kSingleViewInsets{
    /*left=*/5, /*top=*/3, /*right=*/5, /*bottom=*/7};

DocumentLayout::Options::Options() = default;

DocumentLayout::Options::Options(const Options& other) = default;
DocumentLayout::Options& DocumentLayout::Options::operator=(
    const Options& other) = default;

DocumentLayout::Options::~Options() = default;

base::Value DocumentLayout::Options::ToValue() const {
  base::Value dictionary(base::Value::Type::DICTIONARY);
  dictionary.SetIntKey(kDirection, direction_);
  dictionary.SetIntKey(kDefaultPageOrientation,
                       static_cast<int32_t>(default_page_orientation_));
  dictionary.SetBoolKey(kTwoUpViewEnabled,
                        page_spread_ == PageSpread::kTwoUpOdd);
  return dictionary;
}

void DocumentLayout::Options::FromValue(const base::Value& value) {
  DCHECK(value.is_dict());

  int32_t direction = value.FindIntKey(kDirection).value();
  DCHECK_GE(direction, base::i18n::UNKNOWN_DIRECTION);
  DCHECK_LE(direction, base::i18n::TEXT_DIRECTION_MAX);
  direction_ = static_cast<base::i18n::TextDirection>(direction);

  int32_t default_page_orientation =
      value.FindIntKey(kDefaultPageOrientation).value();
  DCHECK_GE(default_page_orientation,
            static_cast<int32_t>(PageOrientation::kOriginal));
  DCHECK_LE(default_page_orientation,
            static_cast<int32_t>(PageOrientation::kLast));
  default_page_orientation_ =
      static_cast<PageOrientation>(default_page_orientation);

  page_spread_ = value.FindBoolKey(kTwoUpViewEnabled).value()
                     ? PageSpread::kTwoUpOdd
                     : PageSpread::kOneUp;
}

void DocumentLayout::Options::RotatePagesClockwise() {
  default_page_orientation_ = RotateClockwise(default_page_orientation_);
}

void DocumentLayout::Options::RotatePagesCounterclockwise() {
  default_page_orientation_ = RotateCounterclockwise(default_page_orientation_);
}

DocumentLayout::DocumentLayout() = default;

DocumentLayout::~DocumentLayout() = default;

void DocumentLayout::SetOptions(const Options& options) {
  // To be conservative, we want to consider the layout dirty for any layout
  // option changes, even if the page rects don't necessarily change when
  // layout options change.
  //
  // We also probably don't want layout changes to actually kick in until
  // the next call to ComputeLayout(). (In practice, we'll call ComputeLayout()
  // shortly after calling SetOptions().)
  if (options_ != options) {
    dirty_ = true;
  }
  options_ = options;
}

void DocumentLayout::ComputeLayout(const std::vector<gfx::Size>& page_sizes) {
  switch (options_.page_spread()) {
    case PageSpread::kOneUp:
      return ComputeOneUpLayout(page_sizes);
    case PageSpread::kTwoUpOdd:
      return ComputeTwoUpOddLayout(page_sizes);
  }
}

void DocumentLayout::ComputeOneUpLayout(
    const std::vector<gfx::Size>& page_sizes) {
  gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);

  if (page_layouts_.size() != page_sizes.size()) {
    // TODO(kmoon): May want to do less work when shrinking a layout.
    page_layouts_.resize(page_sizes.size());
    dirty_ = true;
  }

  for (size_t i = 0; i < page_sizes.size(); ++i) {
    if (i != 0) {
      // Add space for bottom separator.
      document_size.Enlarge(0, kBottomSeparator);
    }

    const gfx::Size& page_size = page_sizes[i];
    gfx::Rect page_rect =
        draw_utils::GetRectForSingleView(page_size, document_size);
    CopyRectIfModified(page_rect, page_layouts_[i].outer_rect);
    CopyRectIfModified(InsetRect(page_rect, kSingleViewInsets),
                       page_layouts_[i].inner_rect);

    draw_utils::ExpandDocumentSize(page_size, &document_size);
  }

  if (size_ != document_size) {
    size_ = document_size;
    dirty_ = true;
  }
}

void DocumentLayout::ComputeTwoUpOddLayout(
    const std::vector<gfx::Size>& page_sizes) {
  gfx::Size document_size(GetWidestPageWidth(page_sizes), 0);

  if (page_layouts_.size() != page_sizes.size()) {
    // TODO(kmoon): May want to do less work when shrinking a layout.
    page_layouts_.resize(page_sizes.size());
    dirty_ = true;
  }

  for (size_t i = 0; i < page_sizes.size(); ++i) {
    draw_utils::PageInsetSizes page_insets =
        draw_utils::GetPageInsetsForTwoUpView(
            i, page_sizes.size(), kSingleViewInsets, kHorizontalSeparator);
    const gfx::Size& page_size = page_sizes[i];

    gfx::Rect page_rect;
    if (i % 2 == 0) {
      page_rect = draw_utils::GetLeftRectForTwoUpView(
          page_size, {document_size.width(), document_size.height()});
    } else {
      page_rect = draw_utils::GetRightRectForTwoUpView(
          page_size, {document_size.width(), document_size.height()});
      document_size.Enlarge(
          0, std::max(page_size.height(), page_sizes[i - 1].height()));
    }
    CopyRectIfModified(page_rect, page_layouts_[i].outer_rect);
    CopyRectIfModified(InsetRect(page_rect, page_insets),
                       page_layouts_[i].inner_rect);
  }

  if (page_sizes.size() % 2 == 1) {
    document_size.Enlarge(0, page_sizes.back().height());
  }

  document_size.set_width(2 * document_size.width());

  if (size_ != document_size) {
    size_ = document_size;
    dirty_ = true;
  }
}

void DocumentLayout::CopyRectIfModified(const gfx::Rect& source_rect,
                                        gfx::Rect& destination_rect) {
  if (destination_rect != source_rect) {
    destination_rect = source_rect;
    dirty_ = true;
  }
}

}  // namespace chrome_pdf
