// Copyright 2013 The Flutter 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 "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/fml/string_conversion.h"
#include "flutter/shell/platform/common/text_editing_delta.h"
#include "flutter/shell/platform/windows/text_input_plugin_delegate.h"

#include <windows.h>

#include <cstdint>

#include "flutter/shell/platform/common/json_method_codec.h"

static constexpr char kSetEditingStateMethod[] = "TextInput.setEditingState";
static constexpr char kClearClientMethod[] = "TextInput.clearClient";
static constexpr char kSetClientMethod[] = "TextInput.setClient";
static constexpr char kShowMethod[] = "TextInput.show";
static constexpr char kHideMethod[] = "TextInput.hide";
static constexpr char kSetMarkedTextRect[] = "TextInput.setMarkedTextRect";
static constexpr char kSetEditableSizeAndTransform[] =
    "TextInput.setEditableSizeAndTransform";

static constexpr char kMultilineInputType[] = "TextInputType.multiline";

static constexpr char kUpdateEditingStateMethod[] =
    "TextInputClient.updateEditingState";
static constexpr char kUpdateEditingStateWithDeltasMethod[] =
    "TextInputClient.updateEditingStateWithDeltas";
static constexpr char kPerformActionMethod[] = "TextInputClient.performAction";

static constexpr char kDeltaOldTextKey[] = "oldText";
static constexpr char kDeltaTextKey[] = "deltaText";
static constexpr char kDeltaStartKey[] = "deltaStart";
static constexpr char kDeltaEndKey[] = "deltaEnd";
static constexpr char kDeltasKey[] = "deltas";
static constexpr char kEnableDeltaModel[] = "enableDeltaModel";
static constexpr char kTextInputAction[] = "inputAction";
static constexpr char kTextInputType[] = "inputType";
static constexpr char kTextInputTypeName[] = "name";
static constexpr char kComposingBaseKey[] = "composingBase";
static constexpr char kComposingExtentKey[] = "composingExtent";
static constexpr char kSelectionAffinityKey[] = "selectionAffinity";
static constexpr char kAffinityDownstream[] = "TextAffinity.downstream";
static constexpr char kSelectionBaseKey[] = "selectionBase";
static constexpr char kSelectionExtentKey[] = "selectionExtent";
static constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional";
static constexpr char kTextKey[] = "text";
static constexpr char kXKey[] = "x";
static constexpr char kYKey[] = "y";
static constexpr char kWidthKey[] = "width";
static constexpr char kHeightKey[] = "height";
static constexpr char kTransformKey[] = "transform";

static constexpr char kChannelName[] = "flutter/textinput";

static constexpr char kBadArgumentError[] = "Bad Arguments";
static constexpr char kInternalConsistencyError[] =
    "Internal Consistency Error";

static constexpr char kInputActionNewline[] = "TextInputAction.newline";

namespace flutter {

void TextInputPlugin::TextHook(const std::u16string& text) {
  if (active_model_ == nullptr) {
    return;
  }
  std::u16string text_before_change =
      fml::Utf8ToUtf16(active_model_->GetText());
  TextRange selection_before_change = active_model_->selection();
  active_model_->AddText(text);

  if (enable_delta_model) {
    TextEditingDelta delta =
        TextEditingDelta(text_before_change, selection_before_change, text);
    SendStateUpdateWithDelta(*active_model_, &delta);
  } else {
    SendStateUpdate(*active_model_);
  }
}

void TextInputPlugin::KeyboardHook(int key,
                                   int scancode,
                                   int action,
                                   char32_t character,
                                   bool extended,
                                   bool was_down) {
  if (active_model_ == nullptr) {
    return;
  }
  if (action == WM_KEYDOWN || action == WM_SYSKEYDOWN) {
    // Most editing keys (arrow keys, backspace, delete, etc.) are handled in
    // the framework, so don't need to be handled at this layer.
    switch (key) {
      case VK_RETURN:
        EnterPressed(active_model_.get());
        break;
      default:
        break;
    }
  }
}

TextInputPlugin::TextInputPlugin(flutter::BinaryMessenger* messenger,
                                 TextInputPluginDelegate* delegate)
    : channel_(std::make_unique<flutter::MethodChannel<rapidjson::Document>>(
          messenger,
          kChannelName,
          &flutter::JsonMethodCodec::GetInstance())),
      delegate_(delegate),
      active_model_(nullptr) {
  channel_->SetMethodCallHandler(
      [this](
          const flutter::MethodCall<rapidjson::Document>& call,
          std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
        HandleMethodCall(call, std::move(result));
      });
}

TextInputPlugin::~TextInputPlugin() = default;

void TextInputPlugin::ComposeBeginHook() {
  if (active_model_ == nullptr) {
    return;
  }
  active_model_->BeginComposing();
  if (enable_delta_model) {
    std::string text = active_model_->GetText();
    TextRange selection = active_model_->selection();
    TextEditingDelta delta = TextEditingDelta(text);
    SendStateUpdateWithDelta(*active_model_, &delta);
  } else {
    SendStateUpdate(*active_model_);
  }
}

void TextInputPlugin::ComposeCommitHook() {
  if (active_model_ == nullptr) {
    return;
  }
  std::string text_before_change = active_model_->GetText();
  TextRange selection_before_change = active_model_->selection();
  TextRange composing_before_change = active_model_->composing_range();
  std::string composing_text_before_change = text_before_change.substr(
      composing_before_change.start(), composing_before_change.length());
  active_model_->CommitComposing();

  // We do not trigger SendStateUpdate here.
  //
  // Until a WM_IME_ENDCOMPOSING event, the user is still composing from the OS
  // point of view. Commit events are always immediately followed by another
  // composing event or an end composing event. However, in the brief window
  // between the commit event and the following event, the composing region is
  // collapsed. Notifying the framework of this intermediate state will trigger
  // any framework code designed to execute at the end of composing, such as
  // input formatters, which may try to update the text and send a message back
  // to the engine with changes.
  //
  // This is a particular problem with Korean IMEs, which build up one
  // character at a time in their composing region until a keypress that makes
  // no sense for the in-progress character. At that point, the result
  // character is committed and a compose event is immedidately received with
  // the new composing region.
  //
  // In the case where this event is immediately followed by a composing event,
  // the state will be sent in ComposeChangeHook.
  //
  // In the case where this event is immediately followed by an end composing
  // event, the state will be sent in ComposeEndHook.
}

void TextInputPlugin::ComposeEndHook() {
  if (active_model_ == nullptr) {
    return;
  }
  std::string text_before_change = active_model_->GetText();
  TextRange selection_before_change = active_model_->selection();
  active_model_->CommitComposing();
  active_model_->EndComposing();
  if (enable_delta_model) {
    std::string text = active_model_->GetText();
    TextEditingDelta delta = TextEditingDelta(text);
    SendStateUpdateWithDelta(*active_model_, &delta);
  } else {
    SendStateUpdate(*active_model_);
  }
}

void TextInputPlugin::ComposeChangeHook(const std::u16string& text,
                                        int cursor_pos) {
  if (active_model_ == nullptr) {
    return;
  }
  std::string text_before_change = active_model_->GetText();
  TextRange composing_before_change = active_model_->composing_range();
  active_model_->AddText(text);
  cursor_pos += active_model_->composing_range().extent();
  active_model_->UpdateComposingText(text);
  active_model_->SetSelection(TextRange(cursor_pos, cursor_pos));
  std::string text_after_change = active_model_->GetText();
  if (enable_delta_model) {
    TextEditingDelta delta = TextEditingDelta(
        fml::Utf8ToUtf16(text_before_change), composing_before_change, text);
    SendStateUpdateWithDelta(*active_model_, &delta);
  } else {
    SendStateUpdate(*active_model_);
  }
}

void TextInputPlugin::HandleMethodCall(
    const flutter::MethodCall<rapidjson::Document>& method_call,
    std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
  const std::string& method = method_call.method_name();

  if (method.compare(kShowMethod) == 0 || method.compare(kHideMethod) == 0) {
    // These methods are no-ops.
  } else if (method.compare(kClearClientMethod) == 0) {
    if (active_model_ != nullptr && active_model_->composing()) {
      active_model_->CommitComposing();
      active_model_->EndComposing();
      SendStateUpdate(*active_model_);
    }
    delegate_->OnResetImeComposing();
    active_model_ = nullptr;
  } else if (method.compare(kSetClientMethod) == 0) {
    if (!method_call.arguments() || method_call.arguments()->IsNull()) {
      result->Error(kBadArgumentError, "Method invoked without args");
      return;
    }
    const rapidjson::Document& args = *method_call.arguments();

    const rapidjson::Value& client_id_json = args[0];
    const rapidjson::Value& client_config = args[1];
    if (client_id_json.IsNull()) {
      result->Error(kBadArgumentError, "Could not set client, ID is null.");
      return;
    }
    if (client_config.IsNull()) {
      result->Error(kBadArgumentError,
                    "Could not set client, missing arguments.");
      return;
    }
    client_id_ = client_id_json.GetInt();
    auto enable_delta_model_json = client_config.FindMember(kEnableDeltaModel);
    if (enable_delta_model_json != client_config.MemberEnd() &&
        enable_delta_model_json->value.IsBool()) {
      enable_delta_model = enable_delta_model_json->value.GetBool();
    }
    input_action_ = "";
    auto input_action_json = client_config.FindMember(kTextInputAction);
    if (input_action_json != client_config.MemberEnd() &&
        input_action_json->value.IsString()) {
      input_action_ = input_action_json->value.GetString();
    }
    input_type_ = "";
    auto input_type_info_json = client_config.FindMember(kTextInputType);
    if (input_type_info_json != client_config.MemberEnd() &&
        input_type_info_json->value.IsObject()) {
      auto input_type_json =
          input_type_info_json->value.FindMember(kTextInputTypeName);
      if (input_type_json != input_type_info_json->value.MemberEnd() &&
          input_type_json->value.IsString()) {
        input_type_ = input_type_json->value.GetString();
      }
    }
    active_model_ = std::make_unique<TextInputModel>();
  } else if (method.compare(kSetEditingStateMethod) == 0) {
    if (!method_call.arguments() || method_call.arguments()->IsNull()) {
      result->Error(kBadArgumentError, "Method invoked without args");
      return;
    }
    const rapidjson::Document& args = *method_call.arguments();

    if (active_model_ == nullptr) {
      result->Error(
          kInternalConsistencyError,
          "Set editing state has been invoked, but no client is set.");
      return;
    }
    auto text = args.FindMember(kTextKey);
    if (text == args.MemberEnd() || text->value.IsNull()) {
      result->Error(kBadArgumentError,
                    "Set editing state has been invoked, but without text.");
      return;
    }
    auto base = args.FindMember(kSelectionBaseKey);
    auto extent = args.FindMember(kSelectionExtentKey);
    if (base == args.MemberEnd() || base->value.IsNull() ||
        extent == args.MemberEnd() || extent->value.IsNull()) {
      result->Error(kInternalConsistencyError,
                    "Selection base/extent values invalid.");
      return;
    }
    // Flutter uses -1/-1 for invalid; translate that to 0/0 for the model.
    int selection_base = base->value.GetInt();
    int selection_extent = extent->value.GetInt();
    if (selection_base == -1 && selection_extent == -1) {
      selection_base = selection_extent = 0;
    }
    active_model_->SetText(text->value.GetString());
    active_model_->SetSelection(TextRange(selection_base, selection_extent));

    base = args.FindMember(kComposingBaseKey);
    extent = args.FindMember(kComposingExtentKey);
    if (base == args.MemberEnd() || base->value.IsNull() ||
        extent == args.MemberEnd() || extent->value.IsNull()) {
      result->Error(kInternalConsistencyError,
                    "Composing base/extent values invalid.");
      return;
    }
    int composing_base = base->value.GetInt();
    int composing_extent = base->value.GetInt();
    if (composing_base == -1 && composing_extent == -1) {
      active_model_->EndComposing();
    } else {
      int composing_start = std::min(composing_base, composing_extent);
      int cursor_offset = selection_base - composing_start;
      active_model_->SetComposingRange(
          TextRange(composing_base, composing_extent), cursor_offset);
    }
  } else if (method.compare(kSetMarkedTextRect) == 0) {
    if (!method_call.arguments() || method_call.arguments()->IsNull()) {
      result->Error(kBadArgumentError, "Method invoked without args");
      return;
    }
    const rapidjson::Document& args = *method_call.arguments();
    auto x = args.FindMember(kXKey);
    auto y = args.FindMember(kYKey);
    auto width = args.FindMember(kWidthKey);
    auto height = args.FindMember(kHeightKey);
    if (x == args.MemberEnd() || x->value.IsNull() ||          //
        y == args.MemberEnd() || y->value.IsNull() ||          //
        width == args.MemberEnd() || width->value.IsNull() ||  //
        height == args.MemberEnd() || height->value.IsNull()) {
      result->Error(kInternalConsistencyError,
                    "Composing rect values invalid.");
      return;
    }
    composing_rect_ = {{x->value.GetDouble(), y->value.GetDouble()},
                       {width->value.GetDouble(), height->value.GetDouble()}};

    Rect transformed_rect = GetCursorRect();
    delegate_->OnCursorRectUpdated(transformed_rect);
  } else if (method.compare(kSetEditableSizeAndTransform) == 0) {
    if (!method_call.arguments() || method_call.arguments()->IsNull()) {
      result->Error(kBadArgumentError, "Method invoked without args");
      return;
    }
    const rapidjson::Document& args = *method_call.arguments();
    auto transform = args.FindMember(kTransformKey);
    if (transform == args.MemberEnd() || transform->value.IsNull() ||
        !transform->value.IsArray() || transform->value.Size() != 16) {
      result->Error(kInternalConsistencyError,
                    "EditableText transform invalid.");
      return;
    }
    size_t i = 0;
    for (auto& entry : transform->value.GetArray()) {
      if (entry.IsNull()) {
        result->Error(kInternalConsistencyError,
                      "EditableText transform contains null value.");
        return;
      }
      editabletext_transform_[i / 4][i % 4] = entry.GetDouble();
      ++i;
    }
    Rect transformed_rect = GetCursorRect();
    delegate_->OnCursorRectUpdated(transformed_rect);
  } else {
    result->NotImplemented();
    return;
  }
  // All error conditions return early, so if nothing has gone wrong indicate
  // success.
  result->Success();
}

Rect TextInputPlugin::GetCursorRect() const {
  Point transformed_point = {
      composing_rect_.left() * editabletext_transform_[0][0] +
          composing_rect_.top() * editabletext_transform_[1][0] +
          editabletext_transform_[3][0],
      composing_rect_.left() * editabletext_transform_[0][1] +
          composing_rect_.top() * editabletext_transform_[1][1] +
          editabletext_transform_[3][1]};
  return {transformed_point, composing_rect_.size()};
}

void TextInputPlugin::SendStateUpdate(const TextInputModel& model) {
  auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
  auto& allocator = args->GetAllocator();
  args->PushBack(client_id_, allocator);

  TextRange selection = model.selection();
  rapidjson::Value editing_state(rapidjson::kObjectType);
  editing_state.AddMember(kSelectionAffinityKey, kAffinityDownstream,
                          allocator);
  editing_state.AddMember(kSelectionBaseKey, selection.base(), allocator);
  editing_state.AddMember(kSelectionExtentKey, selection.extent(), allocator);
  editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator);

  int composing_base = model.composing() ? model.composing_range().base() : -1;
  int composing_extent =
      model.composing() ? model.composing_range().extent() : -1;
  editing_state.AddMember(kComposingBaseKey, composing_base, allocator);
  editing_state.AddMember(kComposingExtentKey, composing_extent, allocator);
  editing_state.AddMember(
      kTextKey, rapidjson::Value(model.GetText(), allocator).Move(), allocator);
  args->PushBack(editing_state, allocator);

  channel_->InvokeMethod(kUpdateEditingStateMethod, std::move(args));
}

void TextInputPlugin::SendStateUpdateWithDelta(const TextInputModel& model,
                                               const TextEditingDelta* delta) {
  auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
  auto& allocator = args->GetAllocator();
  args->PushBack(client_id_, allocator);

  rapidjson::Value object(rapidjson::kObjectType);
  rapidjson::Value deltas(rapidjson::kArrayType);
  rapidjson::Value deltaJson(rapidjson::kObjectType);

  deltaJson.AddMember(kDeltaOldTextKey, delta->old_text(), allocator);
  deltaJson.AddMember(kDeltaTextKey, delta->delta_text(), allocator);
  deltaJson.AddMember(kDeltaStartKey, delta->delta_start(), allocator);
  deltaJson.AddMember(kDeltaEndKey, delta->delta_end(), allocator);

  TextRange selection = model.selection();
  deltaJson.AddMember(kSelectionAffinityKey, kAffinityDownstream, allocator);
  deltaJson.AddMember(kSelectionBaseKey, selection.base(), allocator);
  deltaJson.AddMember(kSelectionExtentKey, selection.extent(), allocator);
  deltaJson.AddMember(kSelectionIsDirectionalKey, false, allocator);

  int composing_base = model.composing() ? model.composing_range().base() : -1;
  int composing_extent =
      model.composing() ? model.composing_range().extent() : -1;
  deltaJson.AddMember(kComposingBaseKey, composing_base, allocator);
  deltaJson.AddMember(kComposingExtentKey, composing_extent, allocator);

  deltas.PushBack(deltaJson, allocator);
  object.AddMember(kDeltasKey, deltas, allocator);
  args->PushBack(object, allocator);

  channel_->InvokeMethod(kUpdateEditingStateWithDeltasMethod, std::move(args));
}

void TextInputPlugin::EnterPressed(TextInputModel* model) {
  if (input_type_ == kMultilineInputType &&
      input_action_ == kInputActionNewline) {
    std::u16string text_before_change = fml::Utf8ToUtf16(model->GetText());
    TextRange selection_before_change = model->selection();
    model->AddText(u"\n");
    if (enable_delta_model) {
      TextEditingDelta delta(text_before_change, selection_before_change,
                             u"\n");
      SendStateUpdateWithDelta(*model, &delta);
    } else {
      SendStateUpdate(*model);
    }
  }
  auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
  auto& allocator = args->GetAllocator();
  args->PushBack(client_id_, allocator);
  args->PushBack(rapidjson::Value(input_action_, allocator).Move(), allocator);

  channel_->InvokeMethod(kPerformActionMethod, std::move(args));
}

}  // namespace flutter
