// Copyright (c) 2016 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 "base/stl_util.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/renderer/core/dom/focus_params.h"
#include "third_party/blink/renderer/core/editing/commands/editing_command_type.h"
#include "third_party/blink/renderer/core/editing/commands/editor_command.h"
#include "third_party/blink/renderer/core/editing/commands/editor_command_names.h"
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/selection_template.h"
#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"

namespace blink {

namespace {

struct CommandNameEntry {
  const char* name;
  EditingCommandType type;
};

const CommandNameEntry kCommandNameEntries[] = {
#define V(name) {#name, EditingCommandType::k##name},
    FOR_EACH_BLINK_EDITING_COMMAND_NAME(V)
#undef V
};
// Test all commands except EditingCommandType::Invalid.
static_assert(
    base::size(kCommandNameEntries) + 1 ==
        static_cast<size_t>(EditingCommandType::kNumberOfCommandTypes),
    "must test all valid EditingCommandType");

}  // anonymous namespace

class EditingCommandTest : public EditingTestBase {};

TEST_F(EditingCommandTest, EditorCommandOrder) {
  for (size_t i = 1; i < base::size(kCommandNameEntries); ++i) {
    EXPECT_GT(0,
              WTF::CodeUnitCompareIgnoringASCIICase(
                  kCommandNameEntries[i - 1].name, kCommandNameEntries[i].name))
        << "EDITOR_COMMAND_MAP must be case-folding ordered. Incorrect index:"
        << i;
  }
}

TEST_F(EditingCommandTest, CreateCommandFromString) {
  Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
  for (const auto& entry : kCommandNameEntries) {
    const EditorCommand command = dummy_editor.CreateCommand(entry.name);
    EXPECT_EQ(static_cast<int>(entry.type), command.IdForHistogram())
        << entry.name;
  }
}

TEST_F(EditingCommandTest, CreateCommandFromStringCaseFolding) {
  Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
  for (const auto& entry : kCommandNameEntries) {
    const EditorCommand lower_name_command =
        dummy_editor.CreateCommand(String(entry.name).LowerASCII());
    EXPECT_EQ(static_cast<int>(entry.type), lower_name_command.IdForHistogram())
        << entry.name;
    const EditorCommand upper_name_command =
        dummy_editor.CreateCommand(String(entry.name).UpperASCII());
    EXPECT_EQ(static_cast<int>(entry.type), upper_name_command.IdForHistogram())
        << entry.name;
  }
}

TEST_F(EditingCommandTest, CreateCommandFromInvalidString) {
  const String kInvalidCommandName[] = {
      "", "iNvAlId", "12345",
  };
  Editor& dummy_editor = GetDocument().GetFrame()->GetEditor();
  for (const auto& command_name : kInvalidCommandName) {
    const EditorCommand command = dummy_editor.CreateCommand(command_name);
    EXPECT_EQ(0, command.IdForHistogram());
  }
}

TEST_F(EditingCommandTest, EnabledVisibleSelection) {
  Editor& editor = GetDocument().GetFrame()->GetEditor();
  const EditorCommand command =
      editor.CreateCommand("MoveRightAndModifySelection");
  Selection().SetSelection(
      SetSelectionTextToBody("<div contenteditable>a|b<div>"),
      SetSelectionOptions());
  Element* div = GetDocument().QuerySelector("div");
  GetDocument().SetFocusedElement(
      div, FocusParams(SelectionBehaviorOnFocus::kNone,
                       mojom::blink::FocusType::kNone, nullptr));
  EXPECT_TRUE(command.IsEnabled());
  div->removeAttribute("contenteditable");
  EXPECT_FALSE(command.IsEnabled());
  GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true);
  EXPECT_TRUE(command.IsEnabled());
}

TEST_F(EditingCommandTest, EnabledVisibleSelectionAndMark) {
  Editor& editor = GetDocument().GetFrame()->GetEditor();
  const EditorCommand command = editor.CreateCommand("SelectToMark");
  Selection().SetSelection(
      SetSelectionTextToBody("<div contenteditable>a|b<div>"),
      SetSelectionOptions());
  Element* div = GetDocument().QuerySelector("div");
  GetDocument().SetFocusedElement(
      div, FocusParams(SelectionBehaviorOnFocus::kNone,
                       mojom::blink::FocusType::kNone, nullptr));
  EXPECT_FALSE(command.IsEnabled());
  editor.SetMark();
  EXPECT_TRUE(command.IsEnabled());
  div->removeAttribute("contenteditable");
  EXPECT_FALSE(command.IsEnabled());
  GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true);
  EXPECT_TRUE(command.IsEnabled());
}

TEST_F(EditingCommandTest, EnabledInEditableTextOrCaretBrowsing) {
  Editor& editor = GetDocument().GetFrame()->GetEditor();
  const EditorCommand command = editor.CreateCommand("MoveRight");

  SetBodyContent("<div>abc</div>");
  GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(false);
  EXPECT_FALSE(command.IsEnabled());
  GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true);
  EXPECT_TRUE(command.IsEnabled());

  GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(false);
  Selection().SetSelection(
      SetSelectionTextToBody("<div contenteditable>a|b<div>"),
      SetSelectionOptions());
  Element* div = GetDocument().QuerySelector("div");
  GetDocument().SetFocusedElement(
      div, FocusParams(SelectionBehaviorOnFocus::kNone,
                       mojom::blink::FocusType::kNone, nullptr));
  EXPECT_TRUE(command.IsEnabled());
  div->removeAttribute("contenteditable");
  EXPECT_FALSE(command.IsEnabled());
}

}  // namespace blink
