/*
 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Google 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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "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 THE COPYRIGHT
 * OWNER 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 "third_party/blink/renderer/core/editing/commands/apply_block_element_command.h"

#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/text.h"
#include "third_party/blink/renderer/core/editing/commands/editing_commands_utilities.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/editing/visible_selection.h"
#include "third_party/blink/renderer/core/editing/visible_units.h"
#include "third_party/blink/renderer/core/html/html_br_element.h"
#include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"

namespace blink {

ApplyBlockElementCommand::ApplyBlockElementCommand(
    Document& document,
    const QualifiedName& tag_name,
    const AtomicString& inline_style)
    : CompositeEditCommand(document),
      tag_name_(tag_name),
      inline_style_(inline_style) {}

ApplyBlockElementCommand::ApplyBlockElementCommand(
    Document& document,
    const QualifiedName& tag_name)
    : CompositeEditCommand(document), tag_name_(tag_name) {}

void ApplyBlockElementCommand::DoApply(EditingState* editing_state) {
  // ApplyBlockElementCommands are only created directly by editor commands'
  // execution, which updates layout before entering doApply().
  DCHECK(!GetDocument().NeedsLayoutTreeUpdate());

  if (!RootEditableElementOf(EndingSelection().Base()))
    return;

  VisiblePosition visible_end = EndingVisibleSelection().VisibleEnd();
  VisiblePosition visible_start = EndingVisibleSelection().VisibleStart();
  if (visible_start.IsNull() || visible_start.IsOrphan() ||
      visible_end.IsNull() || visible_end.IsOrphan())
    return;

  // When a selection ends at the start of a paragraph, we rarely paint
  // the selection gap before that paragraph, because there often is no gap.
  // In a case like this, it's not obvious to the user that the selection
  // ends "inside" that paragraph, so it would be confusing if Indent/Outdent
  // operated on that paragraph.
  // FIXME: We paint the gap before some paragraphs that are indented with left
  // margin/padding, but not others.  We should make the gap painting more
  // consistent and then use a left margin/padding rule here.
  if (visible_end.DeepEquivalent() != visible_start.DeepEquivalent() &&
      IsStartOfParagraph(visible_end)) {
    const Position& new_end =
        PreviousPositionOf(visible_end, kCannotCrossEditingBoundary)
            .DeepEquivalent();
    SelectionInDOMTree::Builder builder;
    builder.Collapse(visible_start.ToPositionWithAffinity());
    if (new_end.IsNotNull())
      builder.Extend(new_end);
    SetEndingSelection(SelectionForUndoStep::From(builder.Build()));
    ABORT_EDITING_COMMAND_IF(EndingVisibleSelection().VisibleStart().IsNull());
    ABORT_EDITING_COMMAND_IF(EndingVisibleSelection().VisibleEnd().IsNull());
  }

  VisibleSelection selection =
      SelectionForParagraphIteration(EndingVisibleSelection());
  VisiblePosition start_of_selection = selection.VisibleStart();
  ABORT_EDITING_COMMAND_IF(start_of_selection.IsNull());
  VisiblePosition end_of_selection = selection.VisibleEnd();
  ABORT_EDITING_COMMAND_IF(end_of_selection.IsNull());
  ContainerNode* start_scope = nullptr;
  int start_index = IndexForVisiblePosition(start_of_selection, start_scope);
  ContainerNode* end_scope = nullptr;
  int end_index = IndexForVisiblePosition(end_of_selection, end_scope);

  // Due to visible position canonicalization, start and end positions could
  // move to different selection contexts one of which could be inside an
  // element that is not editable. e.g. <pre contenteditable>
  //   hello^
  // <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
  // <foreignObject x="20" y="20" width="80" height="80">
  //  L|orem
  // </foreignObject>
  // </svg>
  // </pre>
  if (!IsEditablePosition(start_of_selection.DeepEquivalent()) ||
      !IsEditablePosition(end_of_selection.DeepEquivalent())) {
    return;
  }

  FormatSelection(start_of_selection, end_of_selection, editing_state);
  if (editing_state->IsAborted())
    return;

  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);

  DCHECK_EQ(start_scope, end_scope);
  DCHECK_GE(start_index, 0);
  DCHECK_LE(start_index, end_index);
  if (start_scope == end_scope && start_index >= 0 &&
      start_index <= end_index) {
    VisiblePosition start(VisiblePositionForIndex(start_index, start_scope));
    VisiblePosition end(VisiblePositionForIndex(end_index, end_scope));
    if (start.IsNotNull() && end.IsNotNull()) {
      SetEndingSelection(SelectionForUndoStep::From(
          SelectionInDOMTree::Builder()
              .Collapse(start.ToPositionWithAffinity())
              .Extend(end.DeepEquivalent())
              .Build()));
    }
  }
}

static bool IsAtUnsplittableElement(const Position& pos) {
  Node* node = pos.AnchorNode();
  return node == RootEditableElementOf(pos) ||
         node == EnclosingNodeOfType(pos, &IsTableCell);
}

void ApplyBlockElementCommand::FormatSelection(
    const VisiblePosition& start_of_selection,
    const VisiblePosition& end_of_selection,
    EditingState* editing_state) {
  // Special case empty unsplittable elements because there's nothing to split
  // and there's nothing to move.
  const Position& caret_position =
      MostForwardCaretPosition(start_of_selection.DeepEquivalent());
  if (IsAtUnsplittableElement(caret_position)) {
    HTMLElement* blockquote = CreateBlockElement();
    InsertNodeAt(blockquote, caret_position, editing_state);
    if (editing_state->IsAborted())
      return;
    auto* placeholder = MakeGarbageCollected<HTMLBRElement>(GetDocument());
    AppendNode(placeholder, blockquote, editing_state);
    if (editing_state->IsAborted())
      return;
    SetEndingSelection(SelectionForUndoStep::From(
        SelectionInDOMTree::Builder()
            .Collapse(Position::BeforeNode(*placeholder))
            .Build()));
    return;
  }

  HTMLElement* blockquote_for_next_indent = nullptr;
  VisiblePosition end_of_current_paragraph = EndOfParagraph(start_of_selection);
  const VisiblePosition& visible_end_of_last_paragraph =
      EndOfParagraph(end_of_selection);
  const Position& end_of_next_last_paragraph =
      EndOfParagraph(NextPositionOf(visible_end_of_last_paragraph))
          .DeepEquivalent();
  Position end_of_last_paragraph =
      visible_end_of_last_paragraph.DeepEquivalent();

  bool at_end = false;
  while (end_of_current_paragraph.DeepEquivalent() !=
             end_of_next_last_paragraph &&
         !at_end) {
    if (end_of_current_paragraph.DeepEquivalent() == end_of_last_paragraph)
      at_end = true;

    Position start, end;
    RangeForParagraphSplittingTextNodesIfNeeded(
        end_of_current_paragraph, end_of_last_paragraph, start, end);
    end_of_current_paragraph = CreateVisiblePosition(end);

    Node* enclosing_cell = EnclosingNodeOfType(start, &IsTableCell);
    PositionWithAffinity end_of_next_paragraph =
        EndOfNextParagrahSplittingTextNodesIfNeeded(
            end_of_current_paragraph, end_of_last_paragraph, start, end)
            .ToPositionWithAffinity();

    FormatRange(start, end, end_of_last_paragraph, blockquote_for_next_indent,
                editing_state);
    if (editing_state->IsAborted())
      return;

    // Don't put the next paragraph in the blockquote we just created for this
    // paragraph unless the next paragraph is in the same cell.
    if (enclosing_cell &&
        enclosing_cell !=
            EnclosingNodeOfType(end_of_next_paragraph.GetPosition(),
                                &IsTableCell))
      blockquote_for_next_indent = nullptr;

    // indentIntoBlockquote could move more than one paragraph if the paragraph
    // is in a list item or a table. As a result,
    // |endOfNextLastParagraph| could refer to a position no longer in the
    // document.
    if (end_of_next_last_paragraph.IsNotNull() &&
        !end_of_next_last_paragraph.IsConnected())
      break;
    // Sanity check: Make sure our moveParagraph calls didn't remove
    // endOfNextParagraph.anchorNode() If somehow, e.g. mutation
    // event handler, we did, return to prevent crashes.
    if (end_of_next_paragraph.IsNotNull() &&
        !end_of_next_paragraph.IsConnected())
      return;

    GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
    end_of_current_paragraph = CreateVisiblePosition(end_of_next_paragraph);
  }
}

static bool IsNewLineAtPosition(const Position& position) {
  auto* text_node = DynamicTo<Text>(position.ComputeContainerNode());
  int offset = position.OffsetInContainerNode();
  if (!text_node || offset < 0 ||
      offset >= static_cast<int>(text_node->length()))
    return false;

  DummyExceptionStateForTesting exception_state;
  String text_at_position =
      text_node->substringData(offset, 1, exception_state);
  if (exception_state.HadException())
    return false;

  return text_at_position[0] == '\n';
}

static const ComputedStyle* ComputedStyleOfEnclosingTextNode(
    const Position& position) {
  if (!position.IsOffsetInAnchor() || !position.ComputeContainerNode() ||
      !position.ComputeContainerNode()->IsTextNode())
    return nullptr;
  return position.ComputeContainerNode()->GetComputedStyle();
}

void ApplyBlockElementCommand::RangeForParagraphSplittingTextNodesIfNeeded(
    const VisiblePosition& end_of_current_paragraph,
    Position& end_of_last_paragraph,
    Position& start,
    Position& end) {
  start = StartOfParagraph(end_of_current_paragraph).DeepEquivalent();
  end = end_of_current_paragraph.DeepEquivalent();

  bool is_start_and_end_on_same_node = false;
  if (const ComputedStyle* start_style =
          ComputedStyleOfEnclosingTextNode(start)) {
    is_start_and_end_on_same_node =
        ComputedStyleOfEnclosingTextNode(end) &&
        start.ComputeContainerNode() == end.ComputeContainerNode();
    bool is_start_and_end_of_last_paragraph_on_same_node =
        ComputedStyleOfEnclosingTextNode(end_of_last_paragraph) &&
        start.ComputeContainerNode() ==
            end_of_last_paragraph.ComputeContainerNode();

    // Avoid obtanining the start of next paragraph for start
    // TODO(yosin) We should use |PositionMoveType::CodePoint| for
    // |previousPositionOf()|.
    if (start_style->PreserveNewline() && IsNewLineAtPosition(start) &&
        !IsNewLineAtPosition(
            PreviousPositionOf(start, PositionMoveType::kCodeUnit)) &&
        start.OffsetInContainerNode() > 0)
      start = StartOfParagraph(CreateVisiblePosition(PreviousPositionOf(
                                   end, PositionMoveType::kCodeUnit)))
                  .DeepEquivalent();

    // If start is in the middle of a text node, split.
    if (!start_style->CollapseWhiteSpace() &&
        start.OffsetInContainerNode() > 0) {
      int start_offset = start.OffsetInContainerNode();
      auto* start_text = To<Text>(start.ComputeContainerNode());
      SplitTextNode(start_text, start_offset);
      GetDocument().UpdateStyleAndLayoutTree();

      start = Position::FirstPositionInNode(*start_text);
      if (is_start_and_end_on_same_node) {
        DCHECK_GE(end.OffsetInContainerNode(), start_offset);
        end = Position(start_text, end.OffsetInContainerNode() - start_offset);
      }
      if (is_start_and_end_of_last_paragraph_on_same_node) {
        DCHECK_GE(end_of_last_paragraph.OffsetInContainerNode(), start_offset);
        end_of_last_paragraph =
            Position(start_text, end_of_last_paragraph.OffsetInContainerNode() -
                                     start_offset);
      }
    }
  }

  if (const ComputedStyle* end_style = ComputedStyleOfEnclosingTextNode(end)) {
    bool is_end_and_end_of_last_paragraph_on_same_node =
        ComputedStyleOfEnclosingTextNode(end_of_last_paragraph) &&
        end.AnchorNode() == end_of_last_paragraph.AnchorNode();
    // Include \n at the end of line if we're at an empty paragraph
    if (end_style->PreserveNewline() && start == end &&
        end.OffsetInContainerNode() <
            static_cast<int>(To<Text>(end.ComputeContainerNode())->length())) {
      int end_offset = end.OffsetInContainerNode();
      // TODO(yosin) We should use |PositionMoveType::CodePoint| for
      // |previousPositionOf()|.
      if (!IsNewLineAtPosition(
              PreviousPositionOf(end, PositionMoveType::kCodeUnit)) &&
          IsNewLineAtPosition(end))
        end = Position(end.ComputeContainerNode(), end_offset + 1);
      if (is_end_and_end_of_last_paragraph_on_same_node &&
          end.OffsetInContainerNode() >=
              end_of_last_paragraph.OffsetInContainerNode())
        end_of_last_paragraph = end;
    }

    // If end is in the middle of a text node, split.
    if (end_style->UserModify() != EUserModify::kReadOnly &&
        !end_style->CollapseWhiteSpace() && end.OffsetInContainerNode() &&
        end.OffsetInContainerNode() <
            static_cast<int>(To<Text>(end.ComputeContainerNode())->length())) {
      auto* end_container = To<Text>(end.ComputeContainerNode());
      SplitTextNode(end_container, end.OffsetInContainerNode());
      GetDocument().UpdateStyleAndLayoutTree();

      const Node* const previous_sibling_of_end =
          end_container->previousSibling();
      DCHECK(previous_sibling_of_end);
      if (is_start_and_end_on_same_node) {
        start = FirstPositionInOrBeforeNode(*previous_sibling_of_end);
      }
      if (is_end_and_end_of_last_paragraph_on_same_node) {
        if (end_of_last_paragraph.OffsetInContainerNode() ==
            end.OffsetInContainerNode()) {
          end_of_last_paragraph =
              LastPositionInOrAfterNode(*previous_sibling_of_end);
        } else {
          end_of_last_paragraph = Position(
              end_container, end_of_last_paragraph.OffsetInContainerNode() -
                                 end.OffsetInContainerNode());
        }
      }
      end = Position::LastPositionInNode(*previous_sibling_of_end);
    }
  }
}

VisiblePosition
ApplyBlockElementCommand::EndOfNextParagrahSplittingTextNodesIfNeeded(
    VisiblePosition& end_of_current_paragraph,
    Position& end_of_last_paragraph,
    Position& start,
    Position& end) {
  const VisiblePosition& end_of_next_paragraph =
      EndOfParagraph(NextPositionOf(end_of_current_paragraph));
  const Position& end_of_next_paragraph_position =
      end_of_next_paragraph.DeepEquivalent();
  const ComputedStyle* style =
      ComputedStyleOfEnclosingTextNode(end_of_next_paragraph_position);
  if (!style)
    return end_of_next_paragraph;

  auto* const end_of_next_paragraph_text =
      To<Text>(end_of_next_paragraph_position.ComputeContainerNode());
  if (!style->PreserveNewline() ||
      !end_of_next_paragraph_position.OffsetInContainerNode() ||
      !IsNewLineAtPosition(
          Position::FirstPositionInNode(*end_of_next_paragraph_text)))
    return end_of_next_paragraph;

  // \n at the beginning of the text node immediately following the current
  // paragraph is trimmed by moveParagraphWithClones. If endOfNextParagraph was
  // pointing at this same text node, endOfNextParagraph will be shifted by one
  // paragraph. Avoid this by splitting "\n"
  SplitTextNode(end_of_next_paragraph_text, 1);
  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
  Text* const previous_text =
      DynamicTo<Text>(end_of_next_paragraph_text->previousSibling());
  if (end_of_next_paragraph_text == start.ComputeContainerNode() &&
      previous_text) {
    DCHECK_LT(start.OffsetInContainerNode(),
              end_of_next_paragraph_position.OffsetInContainerNode());
    start = Position(previous_text, start.OffsetInContainerNode());
  }
  if (end_of_next_paragraph_text == end.ComputeContainerNode() &&
      previous_text) {
    DCHECK_LT(end.OffsetInContainerNode(),
              end_of_next_paragraph_position.OffsetInContainerNode());
    end = Position(previous_text, end.OffsetInContainerNode());
  }
  if (end_of_next_paragraph_text ==
      end_of_last_paragraph.ComputeContainerNode()) {
    if (end_of_last_paragraph.OffsetInContainerNode() <
        end_of_next_paragraph_position.OffsetInContainerNode()) {
      // We can only fix endOfLastParagraph if the previous node was still text
      // and hasn't been modified by script.
      if (previous_text && static_cast<unsigned>(
                               end_of_last_paragraph.OffsetInContainerNode()) <=
                               previous_text->length()) {
        end_of_last_paragraph = Position(
            previous_text, end_of_last_paragraph.OffsetInContainerNode());
      }
    } else {
      end_of_last_paragraph =
          Position(end_of_next_paragraph_text,
                   end_of_last_paragraph.OffsetInContainerNode() - 1);
    }
  }

  return CreateVisiblePosition(
      Position(end_of_next_paragraph_text,
               end_of_next_paragraph_position.OffsetInContainerNode() - 1));
}

HTMLElement* ApplyBlockElementCommand::CreateBlockElement() const {
  HTMLElement* element = CreateHTMLElement(GetDocument(), tag_name_);
  if (inline_style_.length())
    element->setAttribute(html_names::kStyleAttr, inline_style_);
  return element;
}

}  // namespace blink
