/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
 * Copyright (C) 2009 Igalia S.L.
 *
 * 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.
 */

// Copyright 2018 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 "third_party/blink/renderer/core/editing/commands/style_commands.h"

#include "third_party/blink/renderer/core/css/css_computed_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_identifier_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_value_list.h"
#include "third_party/blink/renderer/core/editing/commands/apply_style_command.h"
#include "third_party/blink/renderer/core/editing/editing_behavior.h"
#include "third_party/blink/renderer/core/editing/editing_style_utilities.h"
#include "third_party/blink/renderer/core/editing/editing_tri_state.h"
#include "third_party/blink/renderer/core/editing/editing_utilities.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/visible_position.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/html/html_font_element.h"
#include "third_party/blink/renderer/platform/heap/heap.h"

namespace blink {

void StyleCommands::ApplyStyle(LocalFrame& frame,
                               CSSPropertyValueSet* style,
                               InputEvent::InputType input_type) {
  const VisibleSelection& selection =
      frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated();
  if (selection.IsNone())
    return;
  if (selection.IsCaret()) {
    frame.GetEditor().ComputeAndSetTypingStyle(style, input_type);
    return;
  }
  DCHECK(selection.IsRange()) << selection;
  if (!style)
    return;
  DCHECK(frame.GetDocument());
  MakeGarbageCollected<ApplyStyleCommand>(
      *frame.GetDocument(), MakeGarbageCollected<EditingStyle>(style),
      input_type)
      ->Apply();
}

void StyleCommands::ApplyStyleToSelection(LocalFrame& frame,
                                          CSSPropertyValueSet* style,
                                          InputEvent::InputType input_type) {
  if (!style || style->IsEmpty() || !frame.GetEditor().CanEditRichly())
    return;

  ApplyStyle(frame, style, input_type);
}

bool StyleCommands::ApplyCommandToFrame(LocalFrame& frame,
                                        EditorCommandSource source,
                                        InputEvent::InputType input_type,
                                        CSSPropertyValueSet* style) {
  // TODO(editing-dev): We don't call shouldApplyStyle when the source is DOM;
  // is there a good reason for that?
  switch (source) {
    case EditorCommandSource::kMenuOrKeyBinding:
      ApplyStyleToSelection(frame, style, input_type);
      return true;
    case EditorCommandSource::kDOM:
      ApplyStyle(frame, style, input_type);
      return true;
  }
  NOTREACHED();
  return false;
}

bool StyleCommands::ExecuteApplyStyle(LocalFrame& frame,
                                      EditorCommandSource source,
                                      InputEvent::InputType input_type,
                                      CSSPropertyID property_id,
                                      const String& property_value) {
  DCHECK(frame.GetDocument());
  auto* const style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  style->SetProperty(property_id, property_value, /* important */ false,
                     frame.DomWindow()->GetSecureContextMode());
  return ApplyCommandToFrame(frame, source, input_type, style);
}

bool StyleCommands::ExecuteApplyStyle(LocalFrame& frame,
                                      EditorCommandSource source,
                                      InputEvent::InputType input_type,
                                      CSSPropertyID property_id,
                                      CSSValueID property_value) {
  auto* const style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  style->SetProperty(property_id, property_value);
  return ApplyCommandToFrame(frame, source, input_type, style);
}

bool StyleCommands::ExecuteBackColor(LocalFrame& frame,
                                     Event*,
                                     EditorCommandSource source,
                                     const String& value) {
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kBackgroundColor, value);
}

bool StyleCommands::ExecuteForeColor(LocalFrame& frame,
                                     Event*,
                                     EditorCommandSource source,
                                     const String& value) {
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kColor, value);
}

bool StyleCommands::ExecuteFontName(LocalFrame& frame,
                                    Event*,
                                    EditorCommandSource source,
                                    const String& value) {
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kFontFamily, value);
}

bool StyleCommands::ExecuteFontSize(LocalFrame& frame,
                                    Event*,
                                    EditorCommandSource source,
                                    const String& value) {
  CSSValueID size;
  if (!HTMLFontElement::CssValueFromFontSizeNumber(value, size))
    return false;
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kFontSize, size);
}

bool StyleCommands::ExecuteFontSizeDelta(LocalFrame& frame,
                                         Event*,
                                         EditorCommandSource source,
                                         const String& value) {
  // TODO(hjkim3323@gmail.com): Directly set EditingStyle::font_size_delta_
  // instead of setting it via CSS property
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kInternalFontSizeDelta, value);
}

bool StyleCommands::ExecuteMakeTextWritingDirectionLeftToRight(
    LocalFrame& frame,
    Event*,
    EditorCommandSource,
    const String&) {
  auto* const style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  style->SetProperty(CSSPropertyID::kUnicodeBidi, CSSValueID::kIsolate);
  style->SetProperty(CSSPropertyID::kDirection, CSSValueID::kLtr);
  ApplyStyle(frame, style, InputEvent::InputType::kFormatSetBlockTextDirection);
  return true;
}

bool StyleCommands::ExecuteMakeTextWritingDirectionNatural(LocalFrame& frame,
                                                           Event*,
                                                           EditorCommandSource,
                                                           const String&) {
  auto* const style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  style->SetProperty(CSSPropertyID::kUnicodeBidi, CSSValueID::kNormal);
  ApplyStyle(frame, style, InputEvent::InputType::kFormatSetBlockTextDirection);
  return true;
}

bool StyleCommands::ExecuteMakeTextWritingDirectionRightToLeft(
    LocalFrame& frame,
    Event*,
    EditorCommandSource,
    const String&) {
  auto* const style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  style->SetProperty(CSSPropertyID::kUnicodeBidi, CSSValueID::kIsolate);
  style->SetProperty(CSSPropertyID::kDirection, CSSValueID::kRtl);
  ApplyStyle(frame, style, InputEvent::InputType::kFormatSetBlockTextDirection);
  return true;
}

bool StyleCommands::SelectionStartHasStyle(LocalFrame& frame,
                                           CSSPropertyID property_id,
                                           const String& value) {
  const SecureContextMode secure_context_mode =
      frame.DomWindow()->GetSecureContextMode();

  EditingStyle* const style_to_check = MakeGarbageCollected<EditingStyle>(
      property_id, value, secure_context_mode);
  EditingStyle* const style_at_start =
      EditingStyleUtilities::CreateStyleAtSelectionStart(
          frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(),
          property_id == CSSPropertyID::kBackgroundColor,
          style_to_check->Style());
  return style_to_check->TriStateOfStyle(frame.DomWindow(), style_at_start,
                                         secure_context_mode) !=
         EditingTriState::kFalse;
}

bool StyleCommands::ExecuteToggleStyle(LocalFrame& frame,
                                       EditorCommandSource source,
                                       InputEvent::InputType input_type,
                                       CSSPropertyID property_id,
                                       const char* off_value,
                                       const char* on_value) {
  // Style is considered present when
  // Mac: present at the beginning of selection
  // other: present throughout the selection
  const bool style_is_present =
      frame.GetEditor().Behavior().ShouldToggleStyleBasedOnStartOfSelection()
          ? SelectionStartHasStyle(frame, property_id, on_value)
          : EditingStyle::SelectionHasStyle(frame, property_id, on_value) ==
                EditingTriState::kTrue;

  EditingStyle* const style = MakeGarbageCollected<EditingStyle>(
      property_id, style_is_present ? off_value : on_value,
      frame.DomWindow()->GetSecureContextMode());
  return ApplyCommandToFrame(frame, source, input_type, style->Style());
}

bool StyleCommands::ExecuteToggleBold(LocalFrame& frame,
                                      Event*,
                                      EditorCommandSource source,
                                      const String&) {
  return ExecuteToggleStyle(frame, source, InputEvent::InputType::kFormatBold,
                            CSSPropertyID::kFontWeight, "normal", "bold");
}

bool StyleCommands::ExecuteToggleItalic(LocalFrame& frame,
                                        Event*,
                                        EditorCommandSource source,
                                        const String&) {
  return ExecuteToggleStyle(frame, source, InputEvent::InputType::kFormatItalic,
                            CSSPropertyID::kFontStyle, "normal", "italic");
}

bool StyleCommands::ExecuteSubscript(LocalFrame& frame,
                                     Event*,
                                     EditorCommandSource source,
                                     const String&) {
  return ExecuteToggleStyle(frame, source,
                            InputEvent::InputType::kFormatSubscript,
                            CSSPropertyID::kVerticalAlign, "baseline", "sub");
}

bool StyleCommands::ExecuteSuperscript(LocalFrame& frame,
                                       Event*,
                                       EditorCommandSource source,
                                       const String&) {
  return ExecuteToggleStyle(frame, source,
                            InputEvent::InputType::kFormatSuperscript,
                            CSSPropertyID::kVerticalAlign, "baseline", "super");
}

bool StyleCommands::ExecuteUnscript(LocalFrame& frame,
                                    Event*,
                                    EditorCommandSource source,
                                    const String&) {
  return ExecuteApplyStyle(frame, source, InputEvent::InputType::kNone,
                           CSSPropertyID::kVerticalAlign, "baseline");
}

String StyleCommands::ComputeToggleStyleInList(EditingStyle& selection_style,
                                               CSSPropertyID property_id,
                                               const CSSValue& value) {
  const CSSValue& selected_css_value =
      *selection_style.Style()->GetPropertyCSSValue(property_id);
  if (IsA<CSSValueList>(selected_css_value)) {
    CSSValueList& selected_css_value_list =
        *To<CSSValueList>(selected_css_value).Copy();
    if (!selected_css_value_list.RemoveAll(value))
      selected_css_value_list.Append(value);
    if (selected_css_value_list.length())
      return selected_css_value_list.CssText();
  } else if (selected_css_value.CssText() == "none") {
    return value.CssText();
  }
  return "none";
}

bool StyleCommands::ExecuteToggleStyleInList(LocalFrame& frame,
                                             EditorCommandSource source,
                                             InputEvent::InputType input_type,
                                             CSSPropertyID property_id,
                                             const CSSValue& value) {
  EditingStyle* const selection_style =
      EditingStyleUtilities::CreateStyleAtSelectionStart(
          frame.Selection().ComputeVisibleSelectionInDOMTree());
  if (!selection_style || !selection_style->Style())
    return false;

  const String new_style =
      ComputeToggleStyleInList(*selection_style, property_id, value);

  // TODO(editing-dev): We shouldn't be having to convert new style into text.
  // We should have setPropertyCSSValue.
  auto* const new_mutable_style =
      MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode);
  new_mutable_style->SetProperty(property_id, new_style, /* important */ false,
                                 frame.DomWindow()->GetSecureContextMode());
  return ApplyCommandToFrame(frame, source, input_type, new_mutable_style);
}

bool StyleCommands::ExecuteStrikethrough(LocalFrame& frame,
                                         Event*,
                                         EditorCommandSource source,
                                         const String&) {
  const CSSIdentifierValue& line_through =
      *CSSIdentifierValue::Create(CSSValueID::kLineThrough);
  return ExecuteToggleStyleInList(
      frame, source, InputEvent::InputType::kFormatStrikeThrough,
      CSSPropertyID::kWebkitTextDecorationsInEffect, line_through);
}

bool StyleCommands::ExecuteUnderline(LocalFrame& frame,
                                     Event*,
                                     EditorCommandSource source,
                                     const String&) {
  const CSSIdentifierValue& underline =
      *CSSIdentifierValue::Create(CSSValueID::kUnderline);
  return ExecuteToggleStyleInList(
      frame, source, InputEvent::InputType::kFormatUnderline,
      CSSPropertyID::kWebkitTextDecorationsInEffect, underline);
}

bool StyleCommands::ExecuteStyleWithCSS(LocalFrame& frame,
                                        Event*,
                                        EditorCommandSource,
                                        const String& value) {
  frame.GetEditor().SetShouldStyleWithCSS(
      !EqualIgnoringASCIICase(value, "false"));
  return true;
}

bool StyleCommands::ExecuteUseCSS(LocalFrame& frame,
                                  Event*,
                                  EditorCommandSource,
                                  const String& value) {
  frame.GetEditor().SetShouldStyleWithCSS(
      EqualIgnoringASCIICase(value, "false"));
  return true;
}

// State functions
EditingTriState StyleCommands::StateStyle(LocalFrame& frame,
                                          CSSPropertyID property_id,
                                          const char* desired_value) {
  frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
  if (frame.GetEditor().Behavior().ShouldToggleStyleBasedOnStartOfSelection()) {
    return SelectionStartHasStyle(frame, property_id, desired_value)
               ? EditingTriState::kTrue
               : EditingTriState::kFalse;
  }
  return EditingStyle::SelectionHasStyle(frame, property_id, desired_value);
}

EditingTriState StyleCommands::StateBold(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kFontWeight, "bold");
}

EditingTriState StyleCommands::StateItalic(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kFontStyle, "italic");
}

EditingTriState StyleCommands::StateStrikethrough(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kWebkitTextDecorationsInEffect,
                    "line-through");
}

EditingTriState StyleCommands::StateStyleWithCSS(LocalFrame& frame, Event*) {
  return frame.GetEditor().ShouldStyleWithCSS() ? EditingTriState::kTrue
                                                : EditingTriState::kFalse;
}

EditingTriState StyleCommands::StateSubscript(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kVerticalAlign, "sub");
}

EditingTriState StyleCommands::StateSuperscript(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kVerticalAlign, "super");
}

bool StyleCommands::IsUnicodeBidiNestedOrMultipleEmbeddings(
    CSSValueID value_id) {
  return value_id == CSSValueID::kEmbed ||
         value_id == CSSValueID::kBidiOverride ||
         value_id == CSSValueID::kWebkitIsolate ||
         value_id == CSSValueID::kWebkitIsolateOverride ||
         value_id == CSSValueID::kWebkitPlaintext ||
         value_id == CSSValueID::kIsolate ||
         value_id == CSSValueID::kIsolateOverride ||
         value_id == CSSValueID::kPlaintext;
}

mojo_base::mojom::blink::TextDirection StyleCommands::TextDirectionForSelection(
    const VisibleSelection& selection,
    EditingStyle* typing_style,
    bool& has_nested_or_multiple_embeddings) {
  has_nested_or_multiple_embeddings = true;

  if (selection.IsNone())
    return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

  const Position position = MostForwardCaretPosition(selection.Start());

  const Node* anchor_node = position.AnchorNode();
  if (!anchor_node)
    return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

  Position end;
  if (selection.IsRange()) {
    end = MostBackwardCaretPosition(selection.End());

    DCHECK(end.GetDocument());
    const EphemeralRange caret_range(position.ParentAnchoredEquivalent(),
                                     end.ParentAnchoredEquivalent());
    for (Node& node : caret_range.Nodes()) {
      if (!node.IsStyledElement())
        continue;

      const CSSComputedStyleDeclaration& style =
          *MakeGarbageCollected<CSSComputedStyleDeclaration>(&node);
      const CSSValue* unicode_bidi =
          style.GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi);
      auto* unicode_bidi_identifier_value =
          DynamicTo<CSSIdentifierValue>(unicode_bidi);
      if (!unicode_bidi_identifier_value)
        continue;

      const CSSValueID unicode_bidi_value =
          unicode_bidi_identifier_value->GetValueID();
      if (IsUnicodeBidiNestedOrMultipleEmbeddings(unicode_bidi_value))
        return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;
    }
  }

  if (selection.IsCaret()) {
    mojo_base::mojom::blink::TextDirection direction;
    if (typing_style && typing_style->GetTextDirection(direction)) {
      has_nested_or_multiple_embeddings = false;
      return direction;
    }
    anchor_node = selection.VisibleStart().DeepEquivalent().AnchorNode();
  }
  DCHECK(anchor_node);

  // The selection is either a caret with no typing attributes or a range in
  // which no embedding is added, so just use the start position to decide.
  const Node* block = EnclosingBlock(anchor_node);
  mojo_base::mojom::blink::TextDirection found_direction =
      mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

  for (Node& runner : NodeTraversal::InclusiveAncestorsOf(*anchor_node)) {
    if (runner == block)
      break;
    if (!runner.IsStyledElement())
      continue;

    auto* element = To<Element>(&runner);
    const CSSComputedStyleDeclaration& style =
        *MakeGarbageCollected<CSSComputedStyleDeclaration>(element);
    const CSSValue* unicode_bidi =
        style.GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi);
    auto* unicode_bidi_identifier_value =
        DynamicTo<CSSIdentifierValue>(unicode_bidi);
    if (!unicode_bidi_identifier_value)
      continue;

    const CSSValueID unicode_bidi_value =
        unicode_bidi_identifier_value->GetValueID();
    if (unicode_bidi_value == CSSValueID::kNormal)
      continue;

    if (unicode_bidi_value == CSSValueID::kBidiOverride)
      return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

    DCHECK(EditingStyleUtilities::IsEmbedOrIsolate(unicode_bidi_value))
        << static_cast<int>(unicode_bidi_value);
    const CSSValue* direction =
        style.GetPropertyCSSValue(CSSPropertyID::kDirection);
    auto* direction_identifier_value = DynamicTo<CSSIdentifierValue>(direction);
    if (!direction_identifier_value)
      continue;

    const CSSValueID direction_value = direction_identifier_value->GetValueID();
    if (direction_value != CSSValueID::kLtr &&
        direction_value != CSSValueID::kRtl)
      continue;

    if (found_direction !=
        mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION)
      return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

    // In the range case, make sure that the embedding element persists until
    // the end of the range.
    if (selection.IsRange() && !end.AnchorNode()->IsDescendantOf(element))
      return mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION;

    found_direction =
        direction_value == CSSValueID::kLtr
            ? mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT
            : mojo_base::mojom::blink::TextDirection::RIGHT_TO_LEFT;
  }
  has_nested_or_multiple_embeddings = false;
  return found_direction;
}

EditingTriState StyleCommands::StateTextWritingDirection(
    LocalFrame& frame,
    mojo_base::mojom::blink::TextDirection direction) {
  frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);

  bool has_nested_or_multiple_embeddings;
  mojo_base::mojom::blink::TextDirection selection_direction =
      TextDirectionForSelection(
          frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(),
          frame.GetEditor().TypingStyle(), has_nested_or_multiple_embeddings);
  // TODO(editing-dev): We should be returning MixedTriState when
  // selectionDirection == direction && hasNestedOrMultipleEmbeddings
  return (selection_direction == direction &&
          !has_nested_or_multiple_embeddings)
             ? EditingTriState::kTrue
             : EditingTriState::kFalse;
}

EditingTriState StyleCommands::StateTextWritingDirectionLeftToRight(
    LocalFrame& frame,
    Event*) {
  return StateTextWritingDirection(
      frame, mojo_base::mojom::blink::TextDirection::LEFT_TO_RIGHT);
}

EditingTriState StyleCommands::StateTextWritingDirectionNatural(
    LocalFrame& frame,
    Event*) {
  return StateTextWritingDirection(
      frame, mojo_base::mojom::blink::TextDirection::UNKNOWN_DIRECTION);
}

EditingTriState StyleCommands::StateTextWritingDirectionRightToLeft(
    LocalFrame& frame,
    Event*) {
  return StateTextWritingDirection(
      frame, mojo_base::mojom::blink::TextDirection::RIGHT_TO_LEFT);
}

EditingTriState StyleCommands::StateUnderline(LocalFrame& frame, Event*) {
  return StateStyle(frame, CSSPropertyID::kWebkitTextDecorationsInEffect,
                    "underline");
}

// Value functions
String StyleCommands::SelectionStartCSSPropertyValue(
    LocalFrame& frame,
    CSSPropertyID property_id) {
  EditingStyle* const selection_style =
      EditingStyleUtilities::CreateStyleAtSelectionStart(
          frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(),
          property_id == CSSPropertyID::kBackgroundColor);
  if (!selection_style || !selection_style->Style())
    return String();

  if (property_id == CSSPropertyID::kFontSize)
    return String::Number(selection_style->LegacyFontSize(frame.GetDocument()));
  return selection_style->Style()->GetPropertyValue(property_id);
}

String StyleCommands::ValueStyle(LocalFrame& frame, CSSPropertyID property_id) {
  frame.GetDocument()->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);

  // TODO(editing-dev): Rather than retrieving the style at the start of the
  // current selection, we should retrieve the style present throughout the
  // selection for non-Mac platforms.
  return SelectionStartCSSPropertyValue(frame, property_id);
}

String StyleCommands::ValueBackColor(const EditorInternalCommand&,
                                     LocalFrame& frame,
                                     Event*) {
  return ValueStyle(frame, CSSPropertyID::kBackgroundColor);
}

String StyleCommands::ValueForeColor(const EditorInternalCommand&,
                                     LocalFrame& frame,
                                     Event*) {
  return ValueStyle(frame, CSSPropertyID::kColor);
}

String StyleCommands::ValueFontName(const EditorInternalCommand&,
                                    LocalFrame& frame,
                                    Event*) {
  return ValueStyle(frame, CSSPropertyID::kFontFamily);
}

String StyleCommands::ValueFontSize(const EditorInternalCommand&,
                                    LocalFrame& frame,
                                    Event*) {
  return ValueStyle(frame, CSSPropertyID::kFontSize);
}

String StyleCommands::ValueFontSizeDelta(const EditorInternalCommand&,
                                         LocalFrame& frame,
                                         Event*) {
  return ValueStyle(frame, CSSPropertyID::kInternalFontSizeDelta);
}

}  // namespace blink
