// 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/keyboard_key_handler.h"

#include <windows.h>

#include <iostream>

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

namespace flutter {

namespace {

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

static constexpr char kKeyCodeKey[] = "keyCode";
static constexpr char kScanCodeKey[] = "scanCode";
static constexpr char kCharacterCodePointKey[] = "characterCodePoint";
static constexpr char kModifiersKey[] = "modifiers";
static constexpr char kKeyMapKey[] = "keymap";
static constexpr char kTypeKey[] = "type";
static constexpr char kHandledKey[] = "handled";

static constexpr char kWindowsKeyMap[] = "windows";
static constexpr char kKeyUp[] = "keyup";
static constexpr char kKeyDown[] = "keydown";

// The maximum number of pending events to keep before
// emitting a warning on the console about unhandled events.
static constexpr int kMaxPendingEvents = 1000;

}  // namespace

KeyboardKeyHandler::KeyboardKeyHandlerDelegate::~KeyboardKeyHandlerDelegate() =
    default;

KeyboardKeyHandler::KeyboardKeyHandler(EventRedispatcher redispatch_event)
    : redispatch_event_(redispatch_event), last_sequence_id_(1) {}

KeyboardKeyHandler::~KeyboardKeyHandler() = default;

void KeyboardKeyHandler::TextHook(FlutterWindowsView* view,
                                  const std::u16string& code_point) {}

void KeyboardKeyHandler::AddDelegate(
    std::unique_ptr<KeyboardKeyHandlerDelegate> delegate) {
  delegates_.push_back(std::move(delegate));
}

size_t KeyboardKeyHandler::RedispatchedCount() {
  return pending_redispatches_.size();
}

void KeyboardKeyHandler::RedispatchEvent(std::unique_ptr<PendingEvent> event) {
  // TODO(dkwingsmt) consider adding support for redispatching events for UWP
  // in order to support add-to-app.
  // https://github.com/flutter/flutter/issues/70202
#ifdef WINUWP
  return;
#else
  uint8_t scancode = event->scancode;
  char32_t character = event->character;

  INPUT input_event{
      .type = INPUT_KEYBOARD,
      .ki =
          KEYBDINPUT{
              .wVk = 0,
              .wScan = static_cast<WORD>(event->scancode),
              .dwFlags = static_cast<WORD>(
                  KEYEVENTF_SCANCODE |
                  (event->extended ? KEYEVENTF_EXTENDEDKEY : 0x0) |
                  (event->action == WM_KEYUP ? KEYEVENTF_KEYUP : 0x0)),
          },
  };

  pending_redispatches_.push_back(std::move(event));

  UINT accepted = redispatch_event_(1, &input_event, sizeof(input_event));
  if (accepted != 1) {
    std::cerr << "Unable to synthesize event for unhandled keyboard event "
                 "with scancode "
              << scancode << " (character " << character << ")" << std::endl;
  }
#endif
}

bool KeyboardKeyHandler::KeyboardHook(FlutterWindowsView* view,
                                      int key,
                                      int scancode,
                                      int action,
                                      char32_t character,
                                      bool extended,
                                      bool was_down) {
  std::unique_ptr<PendingEvent> incoming =
      std::make_unique<PendingEvent>(PendingEvent{
          .key = static_cast<uint32_t>(key),
          .scancode = static_cast<uint8_t>(scancode),
          .action = static_cast<uint32_t>(action),
          .character = character,
          .extended = extended,
          .was_down = was_down,
      });
  incoming->hash = ComputeEventHash(*incoming);

  if (RemoveRedispatchedEvent(*incoming)) {
    return false;
  }

  uint64_t sequence_id = ++last_sequence_id_;
  incoming->sequence_id = sequence_id;
  incoming->unreplied = delegates_.size();
  incoming->any_handled = false;

  if (pending_responds_.size() > kMaxPendingEvents) {
    std::cerr
        << "There are " << pending_responds_.size()
        << " keyboard events that have not yet received a response from the "
        << "framework. Are responses being sent?" << std::endl;
  }
  pending_responds_.push_back(std::move(incoming));

  for (const auto& delegate : delegates_) {
    delegate->KeyboardHook(key, scancode, action, character, extended, was_down,
                           [sequence_id, this](bool handled) {
                             ResolvePendingEvent(sequence_id, handled);
                           });
  }

  // |ResolvePendingEvent| might trigger redispatching synchronously,
  // which might occur before |KeyboardHook| is returned. This won't
  // make events out of order though, because |KeyboardHook| will always
  // return true at this time, preventing this event from affecting
  // others.

  return true;
}

bool KeyboardKeyHandler::RemoveRedispatchedEvent(const PendingEvent& incoming) {
  for (auto iter = pending_redispatches_.begin();
       iter != pending_redispatches_.end(); ++iter) {
    if ((*iter)->hash == incoming.hash) {
      pending_redispatches_.erase(iter);
      return true;
    }
  }
  return false;
  ;
}

void KeyboardKeyHandler::ResolvePendingEvent(uint64_t sequence_id,
                                             bool handled) {
  // Find the pending event
  for (auto iter = pending_responds_.begin(); iter != pending_responds_.end();
       ++iter) {
    if ((*iter)->sequence_id == sequence_id) {
      PendingEvent& event = **iter;
      event.any_handled = event.any_handled || handled;
      event.unreplied -= 1;
      assert(event.unreplied >= 0);
      // If all delegates have replied, redispatch if no one handled.
      if (event.unreplied == 0) {
        auto event_ptr = std::move(*iter);
        pending_responds_.erase(iter);
        if (!event_ptr->any_handled) {
          RedispatchEvent(std::move(event_ptr));
        }
      }
      // Return here; |iter| can't do ++ after erase.
      return;
    }
  }
  // The pending event should always be found.
  assert(false);
}

void KeyboardKeyHandler::ComposeBeginHook() {
  // Ignore.
}

void KeyboardKeyHandler::ComposeCommitHook() {
  // Ignore.
}

void KeyboardKeyHandler::ComposeEndHook() {
  // Ignore.
}

void KeyboardKeyHandler::ComposeChangeHook(const std::u16string& text,
                                           int cursor_pos) {
  // Ignore.
}

uint64_t KeyboardKeyHandler::ComputeEventHash(const PendingEvent& event) {
  // Calculate a key event ID based on the scan code of the key pressed,
  // and the flags we care about.
  return event.scancode | (((event.action == WM_KEYUP ? KEYEVENTF_KEYUP : 0x0) |
                            (event.extended ? KEYEVENTF_EXTENDEDKEY : 0x0))
                           << 16);
}

}  // namespace flutter
