// Copyright (c) 2021 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 "chrome/browser/chromeos/input_method/grammar_manager.h"

#include "ash/constants/ash_features.h"
#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/input_method/assistive_window_properties.h"
#include "chrome/browser/chromeos/input_method/ui/suggestion_details.h"
#include "ui/base/ime/chromeos/ime_bridge.h"
#include "ui/base/ime/chromeos/ime_input_context_handler_interface.h"
#include "ui/events/keycodes/dom/dom_code.h"

namespace chromeos {
namespace {

constexpr base::TimeDelta kCheckDelay = base::TimeDelta::FromMilliseconds(500);

}  // namespace

GrammarManager::GrammarManager(
    Profile* profile,
    std::unique_ptr<GrammarServiceClient> grammar_client,
    SuggestionHandlerInterface* suggestion_handler)
    : profile_(profile),
      grammar_client_(std::move(grammar_client)),
      suggestion_handler_(suggestion_handler),
      current_fragment_(gfx::Range(), std::string()),
      suggestion_button_(ui::ime::AssistiveWindowButton{
          .id = ui::ime::ButtonId::kSuggestion,
          .window_type = ui::ime::AssistiveWindowType::kGrammarSuggestion,
      }),
      ignore_button_(ui::ime::AssistiveWindowButton{
          .id = ui::ime::ButtonId::kIgnoreSuggestion,
          .window_type = ui::ime::AssistiveWindowType::kGrammarSuggestion,
      }) {}

GrammarManager::~GrammarManager() = default;

bool GrammarManager::IsOnDeviceGrammarEnabled() {
  return base::FeatureList::IsEnabled(
      chromeos::features::kOnDeviceGrammarCheck);
}

void GrammarManager::OnFocus(int context_id) {
  if (context_id != context_id_) {
    last_text_ = u"";
  }
  context_id_ = context_id;
}

bool GrammarManager::OnKeyEvent(const ui::KeyEvent& event) {
  if (!suggestion_shown_ || event.type() != ui::ET_KEY_PRESSED)
    return false;

  if (event.code() == ui::DomCode::ESCAPE) {
    DismissSuggestion();
    return true;
  }
  if (event.code() == ui::DomCode::TAB) {
    if (highlighted_button_ == ui::ime::ButtonId::kSuggestion) {
      highlighted_button_ = ui::ime::ButtonId::kIgnoreSuggestion;
      SetButtonHighlighted(ignore_button_);
    } else {
      highlighted_button_ = ui::ime::ButtonId::kSuggestion;
      SetButtonHighlighted(suggestion_button_);
    }
    return true;
  }
  if (event.code() == ui::DomCode::ENTER) {
    switch (highlighted_button_) {
      case ui::ime::ButtonId::kSuggestion:
        AcceptSuggestion();
        return true;
      case ui::ime::ButtonId::kIgnoreSuggestion:
        IgnoreSuggestion();
        return true;
      default:
        break;
    }
  }
  return false;
}

void GrammarManager::OnSurroundingTextChanged(const std::u16string& text,
                                              int cursor_pos,
                                              int anchor_pos) {
  if (text != last_text_) {
    if (suggestion_shown_) {
      DismissSuggestion();
    }
    // Grammar check is cpu consuming, so we only send request to ml service
    // when the user has stopped typing for some time.
    delay_timer_.Start(
        FROM_HERE, kCheckDelay,
        base::BindOnce(&GrammarManager::Check, base::Unretained(this), text));

    last_text_ = text;
    return;
  }

  ui::IMEInputContextHandlerInterface* input_context =
      ui::IMEBridge::Get()->GetInputContextHandler();
  if (!input_context)
    return;

  gfx::Range cursor_range = cursor_pos <= anchor_pos
                                ? gfx::Range(cursor_pos, anchor_pos)
                                : gfx::Range(anchor_pos, cursor_pos);
  absl::optional<ui::GrammarFragment> grammar_fragment_opt =
      input_context->GetGrammarFragment(cursor_range);

  if (grammar_fragment_opt) {
    current_fragment_ = grammar_fragment_opt.value();
    std::string error;
    AssistiveWindowProperties properties;
    properties.type = ui::ime::AssistiveWindowType::kGrammarSuggestion;
    properties.candidates = {base::UTF8ToUTF16(current_fragment_.suggestion)};
    properties.visible = true;
    suggestion_handler_->SetAssistiveWindowProperties(context_id_, properties,
                                                      &error);
    if (!error.empty()) {
      LOG(ERROR) << "Fail to show suggestion. " << error;
    }
    highlighted_button_ = ui::ime::ButtonId::kNone;
    suggestion_shown_ = true;
  } else if (suggestion_shown_) {
    DismissSuggestion();
  }
}

void GrammarManager::Check(const std::u16string& text) {
  if (text != last_text_) {
    return;
  }

  ui::IMEInputContextHandlerInterface* input_context =
      ui::IMEBridge::Get()->GetInputContextHandler();
  if (!input_context)
    return;

  input_context->ClearGrammarFragments(gfx::Range(0, text.size()));

  grammar_client_->RequestTextCheck(
      profile_, text,
      base::BindOnce(&GrammarManager::OnGrammarCheckDone,
                     base::Unretained(this), text));
}

void GrammarManager::OnGrammarCheckDone(
    const std::u16string& text,
    bool success,
    const std::vector<ui::GrammarFragment>& results) const {
  if (!success || text != last_text_ || results.empty())
    return;
  ui::IMEInputContextHandlerInterface* input_context =
      ui::IMEBridge::Get()->GetInputContextHandler();
  if (!input_context)
    return;

  input_context->AddGrammarFragments(results);
}

void GrammarManager::DismissSuggestion() {
  std::string error;
  suggestion_handler_->DismissSuggestion(context_id_, &error);
  if (!error.empty()) {
    LOG(ERROR) << "Failed to dismiss suggestion. " << error;
    return;
  }
  suggestion_shown_ = false;
}

void GrammarManager::AcceptSuggestion() {
  if (!suggestion_shown_)
    return;

  DismissSuggestion();

  ui::IMEInputContextHandlerInterface* input_context =
      ui::IMEBridge::Get()->GetInputContextHandler();
  if (!input_context) {
    LOG(ERROR) << "Failed to commit grammar suggestion.";
  }

  // NOTE: GetSurroundingTextInfo() could return a stale cache that no
  // longer reflects reality, due to async-ness between IMF and
  // TextInputClient.
  // TODO(crbug/1194424): Work around the issue or fix
  // GetSurroundingTextInfo().
  const ui::SurroundingTextInfo surrounding_text =
      input_context->GetSurroundingTextInfo();

  // Delete the incorrect grammar fragment.
  input_context->DeleteSurroundingText(
      -static_cast<int>(surrounding_text.selection_range.start() -
                        current_fragment_.range.start()),
      current_fragment_.range.length() -
          surrounding_text.selection_range.length());
  // Insert the suggestion and put cursor after it.
  input_context->CommitText(
      base::UTF8ToUTF16(current_fragment_.suggestion),
      ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
}

void GrammarManager::IgnoreSuggestion() {
  if (!suggestion_shown_)
    return;

  DismissSuggestion();

  ui::IMEInputContextHandlerInterface* input_context =
      ui::IMEBridge::Get()->GetInputContextHandler();
  if (!input_context)
    return;

  input_context->ClearGrammarFragments(current_fragment_.range);
}

void GrammarManager::SetButtonHighlighted(
    const ui::ime::AssistiveWindowButton& button) {
  std::string error;
  suggestion_handler_->SetButtonHighlighted(context_id_, button, true, &error);
  if (!error.empty()) {
    LOG(ERROR) << "Failed to set button highlighted. " << error;
  }
}

}  // namespace chromeos
