/*
 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
 * Copyright (C) 2007 Apple Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/page/PrintContext.h"

#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/layout/LayoutView.h"
#include "core/layout/api/LayoutViewItem.h"
#include "platform/graphics/GraphicsContext.h"

namespace blink {

namespace {

// By shrinking to a width of 75% (1.333f) we will render the correct physical
// dimensions in paged media (i.e. cm, pt,). The shrinkage used
// to be 80% (1.25f) to match other browsers - they have since moved on.
// Wide pages will be scaled down more than this.
const float kPrintingMinimumShrinkFactor = 1.33333333f;

// This number determines how small we are willing to reduce the page content
// in order to accommodate the widest line. If the page would have to be
// reduced smaller to make the widest line fit, we just clip instead (this
// behavior matches MacIE and Mozilla, at least).
// TODO(rhogan): Decide if this quirk is still required.
const float kPrintingMaximumShrinkFactor = 2;

LayoutBoxModelObject* EnclosingBoxModelObject(LayoutObject* object) {
  while (object && !object->IsBoxModelObject())
    object = object->Parent();
  if (!object)
    return nullptr;
  return ToLayoutBoxModelObject(object);
}

bool IsCoordinateInPage(int top, int left, const IntRect& page) {
  return page.X() <= left && left < page.MaxX() && page.Y() <= top &&
         top < page.MaxY();
}

}  // namespace

PrintContext::PrintContext(LocalFrame* frame)
    : frame_(frame), is_printing_(false), linked_destinations_valid_(false) {}

PrintContext::~PrintContext() {
  DCHECK(!is_printing_);
}

void PrintContext::ComputePageRects(const FloatRect& print_rect,
                                    float header_height,
                                    float footer_height,
                                    float user_scale_factor,
                                    float& out_page_height) {
  page_rects_.clear();
  out_page_height = 0;

  if (!IsFrameValid())
    return;

  if (user_scale_factor <= 0) {
    DLOG(ERROR) << "userScaleFactor has bad value " << user_scale_factor;
    return;
  }

  LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem();
  const IntRect& document_rect = view.DocumentRect();
  FloatSize page_size = frame_->ResizePageRectsKeepingRatio(
      FloatSize(print_rect.Width(), print_rect.Height()),
      FloatSize(document_rect.Width(), document_rect.Height()));
  float page_width = page_size.Width();
  float page_height = page_size.Height();

  out_page_height =
      page_height;  // this is the height of the page adjusted by margins
  page_height -= header_height + footer_height;

  if (page_height <= 0) {
    DLOG(ERROR) << "pageHeight has bad value " << page_height;
    return;
  }

  ComputePageRectsWithPageSizeInternal(FloatSize(
      page_width / user_scale_factor, page_height / user_scale_factor));
}

void PrintContext::ComputePageRectsWithPageSize(
    const FloatSize& page_size_in_pixels) {
  page_rects_.clear();
  ComputePageRectsWithPageSizeInternal(page_size_in_pixels);
}

void PrintContext::ComputePageRectsWithPageSizeInternal(
    const FloatSize& page_size_in_pixels) {
  if (!IsFrameValid())
    return;

  LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem();

  IntRect doc_rect = view.DocumentRect();

  int page_width = page_size_in_pixels.Width();
  // We scaled with floating point arithmetic and need to ensure results like
  // 13329.99 are treated as 13330 so that we don't mistakenly assign an extra
  // page for the stray pixel.
  int page_height = page_size_in_pixels.Height() + LayoutUnit::Epsilon();

  bool is_horizontal = view.Style()->IsHorizontalWritingMode();

  int doc_logical_height = is_horizontal ? doc_rect.Height() : doc_rect.Width();
  int page_logical_height = is_horizontal ? page_height : page_width;
  int page_logical_width = is_horizontal ? page_width : page_height;

  int inline_direction_start;
  int inline_direction_end;
  int block_direction_start;
  int block_direction_end;
  if (is_horizontal) {
    if (view.Style()->IsFlippedBlocksWritingMode()) {
      block_direction_start = doc_rect.MaxY();
      block_direction_end = doc_rect.Y();
    } else {
      block_direction_start = doc_rect.Y();
      block_direction_end = doc_rect.MaxY();
    }
    inline_direction_start =
        view.Style()->IsLeftToRightDirection() ? doc_rect.X() : doc_rect.MaxX();
    inline_direction_end =
        view.Style()->IsLeftToRightDirection() ? doc_rect.MaxX() : doc_rect.X();
  } else {
    if (view.Style()->IsFlippedBlocksWritingMode()) {
      block_direction_start = doc_rect.MaxX();
      block_direction_end = doc_rect.X();
    } else {
      block_direction_start = doc_rect.X();
      block_direction_end = doc_rect.MaxX();
    }
    inline_direction_start =
        view.Style()->IsLeftToRightDirection() ? doc_rect.Y() : doc_rect.MaxY();
    inline_direction_end =
        view.Style()->IsLeftToRightDirection() ? doc_rect.MaxY() : doc_rect.Y();
  }

  unsigned page_count = ceilf((float)doc_logical_height / page_logical_height);
  for (unsigned i = 0; i < page_count; ++i) {
    int page_logical_top =
        block_direction_end > block_direction_start
            ? block_direction_start + i * page_logical_height
            : block_direction_start - (i + 1) * page_logical_height;

    int page_logical_left = inline_direction_end > inline_direction_start
                                ? inline_direction_start
                                : inline_direction_start - page_logical_width;
    IntRect page_rect(page_logical_left, page_logical_top, page_logical_width,
                      page_logical_height);
    if (!is_horizontal)
      page_rect = page_rect.TransposedRect();
    page_rects_.push_back(page_rect);
  }
}

void PrintContext::BeginPrintMode(float width, float height) {
  ASSERT(width > 0);
  ASSERT(height > 0);

  // This function can be called multiple times to adjust printing parameters
  // without going back to screen mode.
  is_printing_ = true;

  FloatSize original_page_size = FloatSize(width, height);
  FloatSize min_layout_size = frame_->ResizePageRectsKeepingRatio(
      original_page_size, FloatSize(width * kPrintingMinimumShrinkFactor,
                                    height * kPrintingMinimumShrinkFactor));

  // This changes layout, so callers need to make sure that they don't paint to
  // screen while in printing mode.
  frame_->SetPrinting(
      true, min_layout_size, original_page_size,
      kPrintingMaximumShrinkFactor / kPrintingMinimumShrinkFactor);
}

void PrintContext::EndPrintMode() {
  ASSERT(is_printing_);
  is_printing_ = false;
  if (IsFrameValid())
    frame_->SetPrinting(false, FloatSize(), FloatSize(), 0);
  linked_destinations_.clear();
  linked_destinations_valid_ = false;
}

// static
int PrintContext::PageNumberForElement(Element* element,
                                       const FloatSize& page_size_in_pixels) {
  element->GetDocument().UpdateStyleAndLayout();

  LocalFrame* frame = element->GetDocument().GetFrame();
  FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels);
  ScopedPrintContext print_context(frame);
  print_context->BeginPrintMode(page_rect.Width(), page_rect.Height());

  LayoutBoxModelObject* box =
      EnclosingBoxModelObject(element->GetLayoutObject());
  if (!box)
    return -1;

  FloatSize scaled_page_size = page_size_in_pixels;
  scaled_page_size.Scale(frame->View()->ContentsSize().Width() /
                         page_rect.Width());
  print_context->ComputePageRectsWithPageSize(scaled_page_size);

  int top = box->PixelSnappedOffsetTop(box->OffsetParent());
  int left = box->PixelSnappedOffsetLeft(box->OffsetParent());
  for (size_t page_number = 0; page_number < print_context->PageCount();
       ++page_number) {
    if (IsCoordinateInPage(top, left, print_context->PageRect(page_number)))
      return page_number;
  }
  return -1;
}

void PrintContext::CollectLinkedDestinations(Node* node) {
  for (Node* i = node->firstChild(); i; i = i->nextSibling())
    CollectLinkedDestinations(i);

  if (!node->IsLink() || !node->IsElementNode())
    return;
  const AtomicString& href = ToElement(node)->getAttribute(HTMLNames::hrefAttr);
  if (href.IsNull())
    return;
  KURL url = node->GetDocument().CompleteURL(href);
  if (!url.IsValid())
    return;

  if (url.HasFragmentIdentifier() &&
      EqualIgnoringFragmentIdentifier(url, node->GetDocument().BaseURL())) {
    String name = url.FragmentIdentifier();
    if (Element* element = node->GetDocument().FindAnchor(name))
      linked_destinations_.Set(name, element);
  }
}

void PrintContext::OutputLinkedDestinations(GraphicsContext& context,
                                            const IntRect& page_rect) {
  if (!linked_destinations_valid_) {
    // Collect anchors in the top-level frame only because our PrintContext
    // supports only one namespace for the anchors.
    CollectLinkedDestinations(GetFrame()->GetDocument());
    linked_destinations_valid_ = true;
  }

  for (const auto& entry : linked_destinations_) {
    LayoutObject* layout_object = entry.value->GetLayoutObject();
    if (!layout_object || !layout_object->GetFrameView())
      continue;
    IntRect bounding_box = layout_object->AbsoluteBoundingBoxRect();
    // TODO(bokan): boundingBox looks to be in content coordinates but
    // convertToRootFrame doesn't apply scroll offsets when converting up to
    // the root frame.
    IntPoint point = layout_object->GetFrameView()->ConvertToRootFrame(
        bounding_box.Location());
    if (!page_rect.Contains(point))
      continue;
    point.ClampNegativeToZero();
    context.SetURLDestinationLocation(entry.key, point);
  }
}

// static
String PrintContext::PageProperty(LocalFrame* frame,
                                  const char* property_name,
                                  int page_number) {
  Document* document = frame->GetDocument();
  ScopedPrintContext print_context(frame);
  // Any non-zero size is OK here. We don't care about actual layout. We just
  // want to collect @page rules and figure out what declarations apply on a
  // given page (that may or may not exist).
  print_context->BeginPrintMode(800, 1000);
  RefPtr<ComputedStyle> style = document->StyleForPage(page_number);

  // Implement formatters for properties we care about.
  if (!strcmp(property_name, "margin-left")) {
    if (style->MarginLeft().IsAuto())
      return String("auto");
    return String::Number(style->MarginLeft().Value());
  }
  if (!strcmp(property_name, "line-height"))
    return String::Number(style->LineHeight().Value());
  if (!strcmp(property_name, "font-size"))
    return String::Number(style->GetFontDescription().ComputedPixelSize());
  if (!strcmp(property_name, "font-family"))
    return style->GetFontDescription().Family().Family().GetString();
  if (!strcmp(property_name, "size"))
    return String::Number(style->PageSize().Width()) + ' ' +
           String::Number(style->PageSize().Height());

  return String("pageProperty() unimplemented for: ") + property_name;
}

bool PrintContext::IsPageBoxVisible(LocalFrame* frame, int page_number) {
  return frame->GetDocument()->IsPageBoxVisible(page_number);
}

String PrintContext::PageSizeAndMarginsInPixels(LocalFrame* frame,
                                                int page_number,
                                                int width,
                                                int height,
                                                int margin_top,
                                                int margin_right,
                                                int margin_bottom,
                                                int margin_left) {
  DoubleSize page_size(width, height);
  frame->GetDocument()->PageSizeAndMarginsInPixels(page_number, page_size,
                                                   margin_top, margin_right,
                                                   margin_bottom, margin_left);

  return "(" + String::Number(floor(page_size.Width())) + ", " +
         String::Number(floor(page_size.Height())) + ") " +
         String::Number(margin_top) + ' ' + String::Number(margin_right) + ' ' +
         String::Number(margin_bottom) + ' ' + String::Number(margin_left);
}

// static
int PrintContext::NumberOfPages(LocalFrame* frame,
                                const FloatSize& page_size_in_pixels) {
  frame->GetDocument()->UpdateStyleAndLayout();

  FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels);
  ScopedPrintContext print_context(frame);
  print_context->BeginPrintMode(page_rect.Width(), page_rect.Height());
  // Account for shrink-to-fit.
  FloatSize scaled_page_size = page_size_in_pixels;
  scaled_page_size.Scale(frame->View()->ContentsSize().Width() /
                         page_rect.Width());
  print_context->ComputePageRectsWithPageSize(scaled_page_size);
  return print_context->PageCount();
}

bool PrintContext::IsFrameValid() const {
  return frame_->View() && frame_->GetDocument() &&
         !frame_->GetDocument()->GetLayoutViewItem().IsNull();
}

DEFINE_TRACE(PrintContext) {
  visitor->Trace(frame_);
  visitor->Trace(linked_destinations_);
}

ScopedPrintContext::ScopedPrintContext(LocalFrame* frame)
    : context_(new PrintContext(frame)) {}

ScopedPrintContext::~ScopedPrintContext() {
  context_->EndPrintMode();
}

}  // namespace blink
