/*
 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "core/layout/LayoutTreeAsText.h"

#include "core/css/CSSPropertyValueSet.h"
#include "core/dom/Document.h"
#include "core/dom/PseudoElement.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/VisibleSelection.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/Settings.h"
#include "core/html/HTMLElement.h"
#include "core/html_names.h"
#include "core/layout/LayoutBlockFlow.h"
#include "core/layout/LayoutDetailsMarker.h"
#include "core/layout/LayoutEmbeddedContent.h"
#include "core/layout/LayoutFileUploadControl.h"
#include "core/layout/LayoutInline.h"
#include "core/layout/LayoutListItem.h"
#include "core/layout/LayoutListMarker.h"
#include "core/layout/LayoutTableCell.h"
#include "core/layout/LayoutView.h"
#include "core/layout/line/InlineTextBox.h"
#include "core/layout/ng/inline/ng_inline_fragment_traversal.h"
#include "core/layout/ng/inline/ng_text_fragment.h"
#include "core/layout/ng/list/layout_ng_list_item.h"
#include "core/layout/svg/LayoutSVGImage.h"
#include "core/layout/svg/LayoutSVGInline.h"
#include "core/layout/svg/LayoutSVGInlineText.h"
#include "core/layout/svg/LayoutSVGRoot.h"
#include "core/layout/svg/LayoutSVGShape.h"
#include "core/layout/svg/LayoutSVGText.h"
#include "core/layout/svg/SVGLayoutTreeAsText.h"
#include "core/page/PrintContext.h"
#include "core/paint/PaintLayer.h"
#include "core/paint/compositing/CompositedLayerMapping.h"
#include "platform/LayoutUnit.h"
#include "platform/wtf/HexNumber.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/CharacterNames.h"

namespace blink {

using namespace HTMLNames;

static void PrintBorderStyle(TextStream& ts, const EBorderStyle border_style) {
  switch (border_style) {
    case EBorderStyle::kNone:
      ts << "none";
      break;
    case EBorderStyle::kHidden:
      ts << "hidden";
      break;
    case EBorderStyle::kInset:
      ts << "inset";
      break;
    case EBorderStyle::kGroove:
      ts << "groove";
      break;
    case EBorderStyle::kRidge:
      ts << "ridge";
      break;
    case EBorderStyle::kOutset:
      ts << "outset";
      break;
    case EBorderStyle::kDotted:
      ts << "dotted";
      break;
    case EBorderStyle::kDashed:
      ts << "dashed";
      break;
    case EBorderStyle::kSolid:
      ts << "solid";
      break;
    case EBorderStyle::kDouble:
      ts << "double";
      break;
  }

  ts << " ";
}

static String GetTagName(Node* n) {
  if (n->IsDocumentNode())
    return "";
  if (n->getNodeType() == Node::kCommentNode)
    return "COMMENT";
  return n->nodeName();
}

String QuoteAndEscapeNonPrintables(const String& s) {
  StringBuilder result;
  result.Append('"');
  for (unsigned i = 0; i != s.length(); ++i) {
    UChar c = s[i];
    if (c == '\\') {
      result.Append('\\');
      result.Append('\\');
    } else if (c == '"') {
      result.Append('\\');
      result.Append('"');
    } else if (c == '\n' || c == kNoBreakSpaceCharacter) {
      result.Append(' ');
    } else {
      if (c >= 0x20 && c < 0x7F) {
        result.Append(c);
      } else {
        result.Append('\\');
        result.Append('x');
        result.Append('{');
        HexNumber::AppendUnsignedAsHex(c, result);
        result.Append('}');
      }
    }
  }
  result.Append('"');
  return result.ToString();
}

TextStream& operator<<(TextStream& ts, const Color& c) {
  return ts << c.NameForLayoutTreeAsText();
}

void LayoutTreeAsText::WriteLayoutObject(TextStream& ts,
                                         const LayoutObject& o,
                                         LayoutAsTextBehavior behavior) {
  ts << o.DecoratedName();

  if (behavior & kLayoutAsTextShowAddresses)
    ts << " " << static_cast<const void*>(&o);

  if (o.Style() && o.Style()->ZIndex())
    ts << " zI: " << o.Style()->ZIndex();

  if (o.GetNode()) {
    String tag_name = GetTagName(o.GetNode());
    if (!tag_name.IsEmpty())
      ts << " {" << tag_name << "}";
  }

  LayoutRect rect = o.DebugRect();
  ts << " " << rect;

  if (!(o.IsText() && !o.IsBR())) {
    if (o.IsFileUploadControl())
      ts << " "
         << QuoteAndEscapeNonPrintables(
                ToLayoutFileUploadControl(&o)->FileTextValue());

    if (o.Parent()) {
      Color color = o.ResolveColor(GetCSSPropertyColor());
      if (o.Parent()->ResolveColor(GetCSSPropertyColor()) != color)
        ts << " [color=" << color << "]";

      // Do not dump invalid or transparent backgrounds, since that is the
      // default.
      Color background_color = o.ResolveColor(GetCSSPropertyBackgroundColor());
      if (o.Parent()->ResolveColor(GetCSSPropertyBackgroundColor()) !=
              background_color &&
          background_color.Rgb())
        ts << " [bgcolor=" << background_color << "]";

      Color text_fill_color =
          o.ResolveColor(GetCSSPropertyWebkitTextFillColor());
      if (o.Parent()->ResolveColor(GetCSSPropertyWebkitTextFillColor()) !=
              text_fill_color &&
          text_fill_color != color && text_fill_color.Rgb())
        ts << " [textFillColor=" << text_fill_color << "]";

      Color text_stroke_color =
          o.ResolveColor(GetCSSPropertyWebkitTextStrokeColor());
      if (o.Parent()->ResolveColor(GetCSSPropertyWebkitTextStrokeColor()) !=
              text_stroke_color &&
          text_stroke_color != color && text_stroke_color.Rgb())
        ts << " [textStrokeColor=" << text_stroke_color << "]";

      if (o.Parent()->Style()->TextStrokeWidth() !=
              o.Style()->TextStrokeWidth() &&
          o.Style()->TextStrokeWidth() > 0)
        ts << " [textStrokeWidth=" << o.Style()->TextStrokeWidth() << "]";
    }

    if (!o.IsBoxModelObject())
      return;

    const LayoutBoxModelObject& box = ToLayoutBoxModelObject(o);
    if (box.BorderTop() || box.BorderRight() || box.BorderBottom() ||
        box.BorderLeft()) {
      ts << " [border:";

      BorderValue prev_border = o.Style()->BorderTop();
      if (!box.BorderTop()) {
        ts << " none";
      } else {
        ts << " (" << box.BorderTop() << "px ";
        PrintBorderStyle(ts, o.Style()->BorderTopStyle());
        ts << o.ResolveColor(GetCSSPropertyBorderTopColor()) << ")";
      }

      if (!o.Style()->BorderRightEquals(prev_border)) {
        prev_border = o.Style()->BorderRight();
        if (!box.BorderRight()) {
          ts << " none";
        } else {
          ts << " (" << box.BorderRight() << "px ";
          PrintBorderStyle(ts, o.Style()->BorderRightStyle());
          ts << o.ResolveColor(GetCSSPropertyBorderRightColor()) << ")";
        }
      }

      if (!o.Style()->BorderBottomEquals(prev_border)) {
        prev_border = box.Style()->BorderBottom();
        if (!box.BorderBottom()) {
          ts << " none";
        } else {
          ts << " (" << box.BorderBottom() << "px ";
          PrintBorderStyle(ts, o.Style()->BorderBottomStyle());
          ts << o.ResolveColor(GetCSSPropertyBorderBottomColor()) << ")";
        }
      }

      if (!o.Style()->BorderLeftEquals(prev_border)) {
        prev_border = o.Style()->BorderLeft();
        if (!box.BorderLeft()) {
          ts << " none";
        } else {
          ts << " (" << box.BorderLeft() << "px ";
          PrintBorderStyle(ts, o.Style()->BorderLeftStyle());
          ts << o.ResolveColor(GetCSSPropertyBorderLeftColor()) << ")";
        }
      }

      ts << "]";
    }
  }

  if (o.IsTableCell()) {
    const LayoutTableCell& c = ToLayoutTableCell(o);
    ts << " [r=" << c.RowIndex() << " c=" << c.AbsoluteColumnIndex()
       << " rs=" << c.ResolvedRowSpan() << " cs=" << c.ColSpan() << "]";
  }

  if (o.IsDetailsMarker()) {
    ts << ": ";
    switch (ToLayoutDetailsMarker(&o)->GetOrientation()) {
      case LayoutDetailsMarker::kLeft:
        ts << "left";
        break;
      case LayoutDetailsMarker::kRight:
        ts << "right";
        break;
      case LayoutDetailsMarker::kUp:
        ts << "up";
        break;
      case LayoutDetailsMarker::kDown:
        ts << "down";
        break;
    }
  }

  if (o.IsListMarker()) {
    String text = ToLayoutListMarker(o).GetText();
    if (!text.IsEmpty()) {
      if (text.length() != 1) {
        text = QuoteAndEscapeNonPrintables(text);
      } else {
        switch (text[0]) {
          case kBulletCharacter:
            text = "bullet";
            break;
          case kBlackSquareCharacter:
            text = "black square";
            break;
          case kWhiteBulletCharacter:
            text = "white bullet";
            break;
          default:
            text = QuoteAndEscapeNonPrintables(text);
        }
      }
      ts << ": " << text;
    }
  }

  if (behavior & kLayoutAsTextShowIDAndClass) {
    Node* node = o.GetNode();
    if (node && node->IsElementNode()) {
      Element& element = ToElement(*node);
      if (element.HasID())
        ts << " id=\"" + element.GetIdAttribute() + "\"";

      if (element.HasClass()) {
        ts << " class=\"";
        for (size_t i = 0; i < element.ClassNames().size(); ++i) {
          if (i > 0)
            ts << " ";
          ts << element.ClassNames()[i];
        }
        ts << "\"";
      }
    }
  }

  if (behavior & kLayoutAsTextShowLayoutState) {
    bool needs_layout = o.SelfNeedsLayout() ||
                        o.NeedsPositionedMovementLayout() ||
                        o.PosChildNeedsLayout() || o.NormalChildNeedsLayout();
    if (needs_layout)
      ts << " (needs layout:";

    bool have_previous = false;
    if (o.SelfNeedsLayout()) {
      ts << " self";
      have_previous = true;
    }

    if (o.NeedsPositionedMovementLayout()) {
      if (have_previous)
        ts << ",";
      have_previous = true;
      ts << " positioned movement";
    }

    if (o.NormalChildNeedsLayout()) {
      if (have_previous)
        ts << ",";
      have_previous = true;
      ts << " child";
    }

    if (o.PosChildNeedsLayout()) {
      if (have_previous)
        ts << ",";
      ts << " positioned child";
    }

    if (needs_layout)
      ts << ")";
  }
}

static void WriteInlineBox(TextStream& ts, const InlineBox& box, int indent) {
  WriteIndent(ts, indent);
  ts << "+ ";
  ts << box.BoxName() << " {" << box.GetLineLayoutItem().DebugName() << "}"
     << " pos=(" << box.X() << "," << box.Y() << ")"
     << " size=(" << box.Width() << "," << box.Height() << ")"
     << " baseline=" << box.BaselinePosition(kAlphabeticBaseline) << "/"
     << box.BaselinePosition(kIdeographicBaseline);
}

static void WriteInlineTextBox(TextStream& ts,
                               const InlineTextBox& text_box,
                               int indent) {
  WriteInlineBox(ts, text_box, indent);
  String value = text_box.GetText();
  value.Replace('\\', "\\\\");
  value.Replace('\n', "\\n");
  value.Replace('"', "\\\"");
  ts << " range=(" << text_box.Start() << ","
     << (text_box.Start() + text_box.Len()) << ")"
     << " \"" << value << "\"";
}

static void WriteInlineFlowBox(TextStream& ts,
                               const InlineFlowBox& root_box,
                               int indent) {
  WriteInlineBox(ts, root_box, indent);
  ts << "\n";
  for (const InlineBox* box = root_box.FirstChild(); box;
       box = box->NextOnLine()) {
    if (box->IsInlineFlowBox()) {
      WriteInlineFlowBox(ts, static_cast<const InlineFlowBox&>(*box),
                         indent + 1);
      continue;
    }
    if (box->IsInlineTextBox())
      WriteInlineTextBox(ts, static_cast<const InlineTextBox&>(*box),
                         indent + 1);
    else
      WriteInlineBox(ts, *box, indent + 1);
    ts << "\n";
  }
}

void LayoutTreeAsText::WriteLineBoxTree(TextStream& ts,
                                        const LayoutBlockFlow& o,
                                        int indent) {
  for (const InlineFlowBox* root_box = o.FirstLineBox(); root_box;
       root_box = root_box->NextLineBox()) {
    WriteInlineFlowBox(ts, *root_box, indent);
  }
}

static void WriteTextRun(TextStream& ts,
                         const LayoutText& o,
                         const InlineTextBox& run) {
  // FIXME: For now use an "enclosingIntRect" model for x, y and logicalWidth,
  // although this makes it harder to detect any changes caused by the
  // conversion to floating point. :(
  int x = run.X().ToInt();
  int y = run.Y().ToInt();
  int logical_width = (run.X() + run.LogicalWidth()).Ceil() - x;

  // FIXME: Table cell adjustment is temporary until results can be updated.
  if (o.ContainingBlock()->IsTableCell())
    y -= ToLayoutTableCell(o.ContainingBlock())->IntrinsicPaddingBefore();

  ts << "text run at (" << x << "," << y << ") width " << logical_width;
  if (!run.IsLeftToRightDirection() || run.DirOverride()) {
    ts << (!run.IsLeftToRightDirection() ? " RTL" : " LTR");
    if (run.DirOverride())
      ts << " override";
  }
  ts << ": "
     << QuoteAndEscapeNonPrintables(
            String(o.GetText()).Substring(run.Start(), run.Len()));
  if (run.HasHyphen())
    ts << " + hyphen string "
       << QuoteAndEscapeNonPrintables(o.Style()->HyphenString());
  ts << "\n";
}

static void WriteTextFragment(TextStream& ts,
                              const NGPhysicalFragment& physical_fragment,
                              NGPhysicalOffset offset_to_container_box) {
  if (!physical_fragment.IsText())
    return;
  const NGPhysicalTextFragment& physical_text_fragment =
      ToNGPhysicalTextFragment(physical_fragment);
  NGTextFragment fragment(physical_fragment.Style().GetWritingMode(),
                          physical_text_fragment);
  // See WriteTextRun() for why we convert to int.
  int x = offset_to_container_box.left.ToInt();
  int y = offset_to_container_box.top.ToInt();
  int logical_width =
      (offset_to_container_box.left + fragment.InlineSize()).Ceil() - x;
  ts << "text run at (" << x << "," << y << ") width " << logical_width;
  ts << ": "
     << QuoteAndEscapeNonPrintables(physical_text_fragment.Text().ToString());
  ts << "\n";
}

static void WritePaintProperties(TextStream& ts,
                                 const LayoutObject& o,
                                 int indent) {
  bool has_fragments = o.FirstFragment().NextFragment();
  if (has_fragments) {
    WriteIndent(ts, indent);
    ts << "fragments:\n";
  }
  int fragment_index = 0;
  for (const auto *fragment = &o.FirstFragment(); fragment;
       fragment = fragment->NextFragment(), ++fragment_index) {
    WriteIndent(ts, indent);
    if (has_fragments)
      ts << " " << fragment_index << ":";
    ts << " paint_offset=(" << fragment->PaintOffset().ToString()
       << ") visual_rect=(" << fragment->VisualRect().ToString() << ")";
    if (fragment->HasLocalBorderBoxProperties()) {
      // To know where they point into the paint property tree, you can dump
      // the tree using ShowAllPropertyTrees(frame_view).
      ts << " state=(" << fragment->LocalBorderBoxProperties().ToString()
         << ")";
    }
    ts << "\n";
  }
}

void Write(TextStream& ts,
           const LayoutObject& o,
           int indent,
           LayoutAsTextBehavior behavior) {
  if (o.IsSVGShape()) {
    Write(ts, ToLayoutSVGShape(o), indent);
    return;
  }
  if (o.IsSVGResourceContainer()) {
    WriteSVGResourceContainer(ts, o, indent);
    return;
  }
  if (o.IsSVGContainer()) {
    WriteSVGContainer(ts, o, indent);
    return;
  }
  if (o.IsSVGRoot()) {
    Write(ts, ToLayoutSVGRoot(o), indent);
    return;
  }
  if (o.IsSVGText()) {
    WriteSVGText(ts, ToLayoutSVGText(o), indent);
    return;
  }
  if (o.IsSVGInline()) {
    WriteSVGInline(ts, ToLayoutSVGInline(o), indent);
    return;
  }
  if (o.IsSVGInlineText()) {
    WriteSVGInlineText(ts, ToLayoutSVGInlineText(o), indent);
    return;
  }
  if (o.IsSVGImage()) {
    WriteSVGImage(ts, ToLayoutSVGImage(o), indent);
    return;
  }

  WriteIndent(ts, indent);

  LayoutTreeAsText::WriteLayoutObject(ts, o, behavior);
  ts << "\n";

  if (behavior & kLayoutAsTextShowPaintProperties) {
    WritePaintProperties(ts, o, indent + 1);
  }

  if ((behavior & kLayoutAsTextShowLineTrees) && o.IsLayoutBlockFlow()) {
    LayoutTreeAsText::WriteLineBoxTree(ts, ToLayoutBlockFlow(o), indent + 1);
  }

  if (o.IsText() && !o.IsBR()) {
    const LayoutText& text = ToLayoutText(o);
    if (const NGPhysicalBoxFragment* box_fragment =
            text.EnclosingBlockFlowFragment()) {
      for (const auto& child :
           NGInlineFragmentTraversal::SelfFragmentsOf(*box_fragment, &text)) {
        WriteIndent(ts, indent + 1);
        WriteTextFragment(ts, *child.fragment, child.offset_to_container_box);
      }
    } else {
      for (InlineTextBox* box = text.FirstTextBox(); box;
           box = box->NextTextBox()) {
        WriteIndent(ts, indent + 1);
        WriteTextRun(ts, text, *box);
      }
    }
  }

  for (LayoutObject* child = o.SlowFirstChild(); child;
       child = child->NextSibling()) {
    if (child->HasLayer())
      continue;
    Write(ts, *child, indent + 1, behavior);
  }

  if (o.IsLayoutEmbeddedContent()) {
    FrameView* frame_view = ToLayoutEmbeddedContent(o).ChildFrameView();
    if (frame_view && frame_view->IsLocalFrameView()) {
      if (auto* layout_view = ToLocalFrameView(frame_view)->GetLayoutView()) {
        layout_view->GetDocument().UpdateStyleAndLayout();
        if (auto* layer = layout_view->Layer()) {
          LayoutTreeAsText::WriteLayers(
              ts, layer, layer, layer->RectIgnoringNeedsPositionUpdate(),
              indent + 1, behavior);
        }
      }
    }
  }
}

enum LayerPaintPhase {
  kLayerPaintPhaseAll = 0,
  kLayerPaintPhaseBackground = -1,
  kLayerPaintPhaseForeground = 1
};

static void Write(TextStream& ts,
                  PaintLayer& layer,
                  const LayoutRect& layer_bounds,
                  const LayoutRect& background_clip_rect,
                  const LayoutRect& clip_rect,
                  LayerPaintPhase paint_phase = kLayerPaintPhaseAll,
                  int indent = 0,
                  LayoutAsTextBehavior behavior = kLayoutAsTextBehaviorNormal,
                  const PaintLayer* marked_layer = nullptr) {
  IntRect adjusted_layout_bounds = PixelSnappedIntRect(layer_bounds);
  IntRect adjusted_layout_bounds_with_scrollbars = adjusted_layout_bounds;
  IntRect adjusted_background_clip_rect =
      PixelSnappedIntRect(background_clip_rect);
  IntRect adjusted_clip_rect = PixelSnappedIntRect(clip_rect);

  bool report_frame_scroll_info =
      layer.GetLayoutObject().IsLayoutView() &&
      !RuntimeEnabledFeatures::RootLayerScrollingEnabled();

  if (report_frame_scroll_info) {
    LayoutView& layout_view = ToLayoutView(layer.GetLayoutObject());

    adjusted_layout_bounds_with_scrollbars.SetWidth(
        layout_view.ViewWidth(kIncludeScrollbars));
    adjusted_layout_bounds_with_scrollbars.SetHeight(
        layout_view.ViewHeight(kIncludeScrollbars));
  }

  if (marked_layer)
    ts << (marked_layer == &layer ? "*" : " ");

  WriteIndent(ts, indent);

  if (layer.GetLayoutObject().Style()->Visibility() == EVisibility::kHidden)
    ts << "hidden ";

  ts << "layer ";

  if (behavior & kLayoutAsTextShowAddresses)
    ts << static_cast<const void*>(&layer) << " ";

  ts << adjusted_layout_bounds_with_scrollbars;

  if (!adjusted_layout_bounds.IsEmpty()) {
    if (!adjusted_background_clip_rect.Contains(adjusted_layout_bounds))
      ts << " backgroundClip " << adjusted_background_clip_rect;
    if (!adjusted_clip_rect.Contains(adjusted_layout_bounds_with_scrollbars))
      ts << " clip " << adjusted_clip_rect;
  }
  if (layer.IsTransparent())
    ts << " transparent";

  if (layer.GetLayoutObject().HasOverflowClip() || report_frame_scroll_info) {
    ScrollableArea* scrollable_area;
    if (report_frame_scroll_info)
      scrollable_area = ToLayoutView(layer.GetLayoutObject()).GetFrameView();
    else
      scrollable_area = layer.GetScrollableArea();

    ScrollOffset adjusted_scroll_offset =
        scrollable_area->GetScrollOffset() +
        ToFloatSize(scrollable_area->ScrollOrigin());
    if (adjusted_scroll_offset.Width())
      ts << " scrollX " << adjusted_scroll_offset.Width();
    if (adjusted_scroll_offset.Height())
      ts << " scrollY " << adjusted_scroll_offset.Height();
    if (layer.GetLayoutBox() &&
        layer.GetLayoutBox()->PixelSnappedClientWidth() !=
            layer.GetLayoutBox()->PixelSnappedScrollWidth())
      ts << " scrollWidth " << layer.GetLayoutBox()->PixelSnappedScrollWidth();
    if (layer.GetLayoutBox() &&
        layer.GetLayoutBox()->PixelSnappedClientHeight() !=
            layer.GetLayoutBox()->PixelSnappedScrollHeight())
      ts << " scrollHeight "
         << layer.GetLayoutBox()->PixelSnappedScrollHeight();
  }

  if (paint_phase == kLayerPaintPhaseBackground)
    ts << " layerType: background only";
  else if (paint_phase == kLayerPaintPhaseForeground)
    ts << " layerType: foreground only";

  if (layer.GetLayoutObject().Style()->HasBlendMode()) {
    ts << " blendMode: "
       << CompositeOperatorName(kCompositeSourceOver,
                                layer.GetLayoutObject().Style()->BlendMode());
  }

  if (behavior & kLayoutAsTextShowCompositedLayers) {
    if (layer.HasCompositedLayerMapping()) {
      ts << " (composited, bounds="
         << layer.GetCompositedLayerMapping()->CompositedBounds()
         << ", drawsContent="
         << layer.GetCompositedLayerMapping()
                ->MainGraphicsLayer()
                ->DrawsContent()
         << (layer.ShouldIsolateCompositedDescendants()
                 ? ", isolatesCompositedBlending"
                 : "")
         << ")";
    }
  }

  ts << "\n";

  if (paint_phase != kLayerPaintPhaseBackground)
    Write(ts, layer.GetLayoutObject(), indent + 1, behavior);
}

static Vector<PaintLayerStackingNode*> NormalFlowListFor(
    PaintLayerStackingNode* node) {
  PaintLayerStackingNodeIterator it(*node, kNormalFlowChildren);
  Vector<PaintLayerStackingNode*> vector;
  while (PaintLayerStackingNode* normal_flow_child = it.Next())
    vector.push_back(normal_flow_child);
  return vector;
}

void LayoutTreeAsText::WriteLayers(TextStream& ts,
                                   const PaintLayer* root_layer,
                                   PaintLayer* layer,
                                   const LayoutRect& paint_rect,
                                   int indent,
                                   LayoutAsTextBehavior behavior,
                                   const PaintLayer* marked_layer) {
  // Calculate the clip rects we should use.
  LayoutRect layer_bounds;
  ClipRect damage_rect, clip_rect_to_apply;
  layer->Clipper(PaintLayer::kUseGeometryMapper)
      .CalculateRects(ClipRectsContext(root_layer, kUncachedClipRects),
                      &layer->GetLayoutObject().FirstFragment(), paint_rect,
                      layer_bounds, damage_rect, clip_rect_to_apply);

  // Ensure our lists are up to date.
  layer->StackingNode()->UpdateLayerListsIfNeeded();

  LayoutPoint offset_from_root;
  layer->ConvertToLayerCoords(root_layer, offset_from_root);
  bool should_paint =
      (behavior & kLayoutAsTextShowAllLayers)
          ? true
          : layer->IntersectsDamageRect(layer_bounds, damage_rect.Rect(),
                                        offset_from_root);

  if (layer->GetLayoutObject().IsLayoutEmbeddedContent() &&
      ToLayoutEmbeddedContent(layer->GetLayoutObject()).IsThrottledFrameView())
    should_paint = false;

#if DCHECK_IS_ON()
  if (layer->NeedsPositionUpdate()) {
    WriteIndent(ts, indent);
    ts << " NEEDS POSITION UPDATE\n";
  }
#endif

  Vector<PaintLayerStackingNode*>* neg_list =
      layer->StackingNode()->NegZOrderList();
  bool paints_background_separately = neg_list && neg_list->size() > 0;
  if (should_paint && paints_background_separately)
    Write(ts, *layer, layer_bounds, damage_rect.Rect(),
          clip_rect_to_apply.Rect(), kLayerPaintPhaseBackground, indent,
          behavior, marked_layer);

  if (neg_list) {
    int curr_indent = indent;
    if (behavior & kLayoutAsTextShowLayerNesting) {
      WriteIndent(ts, indent);
      ts << " negative z-order list(" << neg_list->size() << ")\n";
      ++curr_indent;
    }
    for (unsigned i = 0; i != neg_list->size(); ++i)
      WriteLayers(ts, root_layer, neg_list->at(i)->Layer(), paint_rect,
                  curr_indent, behavior, marked_layer);
  }

  if (should_paint)
    Write(ts, *layer, layer_bounds, damage_rect.Rect(),
          clip_rect_to_apply.Rect(),
          paints_background_separately ? kLayerPaintPhaseForeground
                                       : kLayerPaintPhaseAll,
          indent, behavior, marked_layer);

  Vector<PaintLayerStackingNode*> normal_flow_list =
      NormalFlowListFor(layer->StackingNode());
  if (!normal_flow_list.IsEmpty()) {
    int curr_indent = indent;
    if (behavior & kLayoutAsTextShowLayerNesting) {
      WriteIndent(ts, indent);
      ts << " normal flow list(" << normal_flow_list.size() << ")\n";
      ++curr_indent;
    }
    for (unsigned i = 0; i != normal_flow_list.size(); ++i)
      WriteLayers(ts, root_layer, normal_flow_list.at(i)->Layer(), paint_rect,
                  curr_indent, behavior, marked_layer);
  }

  if (Vector<PaintLayerStackingNode*>* pos_list =
          layer->StackingNode()->PosZOrderList()) {
    int curr_indent = indent;
    if (behavior & kLayoutAsTextShowLayerNesting) {
      WriteIndent(ts, indent);
      ts << " positive z-order list(" << pos_list->size() << ")\n";
      ++curr_indent;
    }
    for (unsigned i = 0; i != pos_list->size(); ++i)
      WriteLayers(ts, root_layer, pos_list->at(i)->Layer(), paint_rect,
                  curr_indent, behavior, marked_layer);
  }
}

static String NodePosition(Node* node) {
  StringBuilder result;

  Element* body = node->GetDocument().body();
  Node* parent;
  for (Node* n = node; n; n = parent) {
    parent = n->ParentOrShadowHostNode();
    if (n != node)
      result.Append(" of ");
    if (parent) {
      if (body && n == body) {
        // We don't care what offset body may be in the document.
        result.Append("body");
        break;
      }
      if (n->IsShadowRoot()) {
        result.Append('{');
        result.Append(GetTagName(n));
        result.Append('}');
      } else {
        result.Append("child ");
        result.AppendNumber(n->NodeIndex());
        result.Append(" {");
        result.Append(GetTagName(n));
        result.Append('}');
      }
    } else {
      result.Append("document");
    }
  }

  return result.ToString();
}

static void WriteSelection(TextStream& ts, const LayoutObject* o) {
  Node* n = o->GetNode();
  if (!n || !n->IsDocumentNode())
    return;

  Document* doc = ToDocument(n);
  LocalFrame* frame = doc->GetFrame();
  if (!frame)
    return;

  const VisibleSelection& selection =
      frame->Selection().ComputeVisibleSelectionInDOMTree();
  if (selection.IsCaret()) {
    ts << "caret: position " << selection.Start().ComputeEditingOffset()
       << " of " << NodePosition(selection.Start().AnchorNode());
    if (selection.Affinity() == TextAffinity::kUpstream)
      ts << " (upstream affinity)";
    ts << "\n";
  } else if (selection.IsRange()) {
    ts << "selection start: position "
       << selection.Start().ComputeEditingOffset() << " of "
       << NodePosition(selection.Start().AnchorNode()) << "\n"
       << "selection end:   position " << selection.End().ComputeEditingOffset()
       << " of " << NodePosition(selection.End().AnchorNode()) << "\n";
  }
}

static String ExternalRepresentation(LayoutBox* layout_object,
                                     LayoutAsTextBehavior behavior,
                                     const PaintLayer* marked_layer = nullptr) {
  TextStream ts;
  if (!layout_object->HasLayer())
    return ts.Release();

  PaintLayer* layer = layout_object->Layer();
  LayoutTreeAsText::WriteLayers(ts, layer, layer,
                                layer->RectIgnoringNeedsPositionUpdate(), 0,
                                behavior, marked_layer);
  WriteSelection(ts, layout_object);
  return ts.Release();
}

String ExternalRepresentation(LocalFrame* frame,
                              LayoutAsTextBehavior behavior,
                              const PaintLayer* marked_layer) {
  if (!(behavior & kLayoutAsTextDontUpdateLayout)) {
    bool success = frame->View()->UpdateLifecycleToPrePaintClean();
    DCHECK(success);
  };

  LayoutObject* layout_object = frame->ContentLayoutObject();
  if (!layout_object || !layout_object->IsBox())
    return String();
  LayoutBox* layout_box = ToLayoutBox(layout_object);

  PrintContext print_context(frame, /*use_printing_layout=*/true);
  bool is_text_printing_mode = !!(behavior & kLayoutAsTextPrintingMode);
  if (is_text_printing_mode) {
    print_context.BeginPrintMode(layout_box->ClientWidth(),
                                 layout_box->ClientHeight());

    // The lifecycle needs to be run again after changing printing mode,
    // to account for any style updates due to media query change.
    if (!(behavior & kLayoutAsTextDontUpdateLayout))
      frame->View()->UpdateLifecyclePhasesForPrinting();
  }

  String representation = ExternalRepresentation(ToLayoutBox(layout_object),
                                                 behavior, marked_layer);
  if (is_text_printing_mode)
    print_context.EndPrintMode();
  return representation;
}

String ExternalRepresentation(Element* element, LayoutAsTextBehavior behavior) {
  // Doesn't support printing mode.
  DCHECK(!(behavior & kLayoutAsTextPrintingMode));
  if (!(behavior & kLayoutAsTextDontUpdateLayout))
    element->GetDocument().UpdateStyleAndLayout();

  LayoutObject* layout_object = element->GetLayoutObject();
  if (!layout_object || !layout_object->IsBox())
    return String();

  return ExternalRepresentation(ToLayoutBox(layout_object),
                                behavior | kLayoutAsTextShowAllLayers);
}

static void WriteCounterValuesFromChildren(TextStream& stream,
                                           LayoutObject* parent,
                                           bool& is_first_counter) {
  for (LayoutObject* child = parent->SlowFirstChild(); child;
       child = child->NextSibling()) {
    if (child->IsCounter()) {
      if (!is_first_counter)
        stream << " ";
      is_first_counter = false;
      String str(ToLayoutText(child)->GetText());
      stream << str;
    }
  }
}

String CounterValueForElement(Element* element) {
  element->GetDocument().UpdateStyleAndLayout();
  TextStream stream;
  bool is_first_counter = true;
  // The counter layoutObjects should be children of :before or :after
  // pseudo-elements.
  if (LayoutObject* before =
          element->PseudoElementLayoutObject(kPseudoIdBefore))
    WriteCounterValuesFromChildren(stream, before, is_first_counter);
  if (LayoutObject* after = element->PseudoElementLayoutObject(kPseudoIdAfter))
    WriteCounterValuesFromChildren(stream, after, is_first_counter);
  return stream.Release();
}

String MarkerTextForListItem(Element* element) {
  element->GetDocument().UpdateStyleAndLayout();

  LayoutObject* layout_object = element->GetLayoutObject();
  if (layout_object) {
    if (layout_object->IsListItem())
      return ToLayoutListItem(layout_object)->MarkerText();
    if (layout_object->IsLayoutNGListItem())
      return ToLayoutNGListItem(layout_object)->MarkerTextWithoutSuffix();
  }
  return String();
}

}  // namespace blink
