// 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 <assert.h>
#include <memory>
#include <string>

#include "flutter/fml/logging.h"
#include "flutter/shell/platform/windows/keyboard_manager.h"
#include "flutter/shell/platform/windows/keyboard_utils.h"

namespace flutter {

namespace {

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

// Returns true if this key is an AltRight key down event.
//
// This is used to resolve an issue where an AltGr press causes CtrlLeft to hang
// when pressed, as reported in https://github.com/flutter/flutter/issues/78005.
//
// When AltGr is pressed (in a supporting layout such as Spanish), Win32 first
// fires a fake CtrlLeft down event, then an AltRight down event.
// This is significant because this fake CtrlLeft down event will not be paired
// with a up event, which is fine until Flutter redispatches the CtrlDown
// event, which Win32 then interprets as a real event, leaving both Win32 and
// the Flutter framework thinking that CtrlLeft is still pressed.
//
// To resolve this, Flutter recognizes this fake CtrlLeft down event using the
// following AltRight down event. Flutter then forges a CtrlLeft key up event
// immediately after the corresponding AltRight key up event.
//
// One catch is that it is impossible to distinguish the fake CtrlLeft down
// from a normal CtrlLeft down (followed by a AltRight down), since they
// contain the exactly same information, including the GetKeyState result.
// Fortunately, this will require the two events to occur *really* close, which
// would be rare, and a misrecognition would only cause a minor consequence
// where the CtrlLeft is released early; the later, real, CtrlLeft up event will
// be ignored.
static bool IsKeyDownAltRight(int action, int virtual_key, bool extended) {
  return virtual_key == VK_RMENU && extended &&
         (action == WM_KEYDOWN || action == WM_SYSKEYDOWN);
}

// Returns true if this key is a key up event of AltRight.
//
// This is used to assist a corner case described in |IsKeyDownAltRight|.
static bool IsKeyUpAltRight(int action, int virtual_key, bool extended) {
  return virtual_key == VK_RMENU && extended &&
         (action == WM_KEYUP || action == WM_SYSKEYUP);
}

// Returns true if this key is a key down event of CtrlLeft.
//
// This is used to assist a corner case described in |IsKeyDownAltRight|.
static bool IsKeyDownCtrlLeft(int action, int virtual_key) {
  return virtual_key == VK_LCONTROL &&
         (action == WM_KEYDOWN || action == WM_SYSKEYDOWN);
}

// Returns if a character sent by Win32 is a dead key.
static bool IsDeadKey(uint32_t ch) {
  return (ch & kDeadKeyCharMask) != 0;
}

static char32_t CodePointFromSurrogatePair(wchar_t high, wchar_t low) {
  return 0x10000 + ((static_cast<char32_t>(high) & 0x000003FF) << 10) +
         (low & 0x3FF);
}

static uint16_t ResolveKeyCode(uint16_t original,
                               bool extended,
                               uint8_t scancode) {
  switch (original) {
    case VK_SHIFT:
    case VK_LSHIFT:
      return MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
    case VK_MENU:
    case VK_LMENU:
      return extended ? VK_RMENU : VK_LMENU;
    case VK_CONTROL:
    case VK_LCONTROL:
      return extended ? VK_RCONTROL : VK_LCONTROL;
    default:
      return original;
  }
}

static bool IsPrintable(uint32_t c) {
  constexpr char32_t kMinPrintable = ' ';
  constexpr char32_t kDelete = 0x7F;
  return c >= kMinPrintable && c != kDelete;
}

static bool IsSysAction(UINT action) {
  return action == WM_SYSKEYDOWN || action == WM_SYSKEYUP ||
         action == WM_SYSCHAR || action == WM_SYSDEADCHAR;
}

}  // namespace

KeyboardManager::KeyboardManager(WindowDelegate* delegate)
    : window_delegate_(delegate),
      last_key_is_ctrl_left_down(false),
      should_synthesize_ctrl_left_up(false),
      processing_event_(false) {}

void KeyboardManager::RedispatchEvent(std::unique_ptr<PendingEvent> event) {
  for (const Win32Message& message : event->session) {
    // Never redispatch sys keys, because their original messages have been
    // passed to the system default processor.
    if (IsSysAction(message.action)) {
      continue;
    }
    pending_redispatches_.push_back(message);
    UINT result = window_delegate_->Win32DispatchMessage(
        message.action, message.wparam, message.lparam);
    if (result != 0) {
      FML_LOG(ERROR) << "Unable to synthesize event for keyboard event.";
    }
  }
  if (pending_redispatches_.size() > kMaxPendingEvents) {
    FML_LOG(ERROR)
        << "There are " << pending_redispatches_.size()
        << " keyboard events that have not yet received a response from the "
        << "framework. Are responses being sent?";
  }
}

bool KeyboardManager::RemoveRedispatchedMessage(UINT const action,
                                                WPARAM const wparam,
                                                LPARAM const lparam) {
  for (auto iter = pending_redispatches_.begin();
       iter != pending_redispatches_.end(); ++iter) {
    if (action == iter->action && wparam == iter->wparam) {
      pending_redispatches_.erase(iter);
      return true;
    }
  }
  return false;
}

bool KeyboardManager::HandleMessage(UINT const action,
                                    WPARAM const wparam,
                                    LPARAM const lparam) {
  if (RemoveRedispatchedMessage(action, wparam, lparam)) {
    return false;
  }
  switch (action) {
    case WM_DEADCHAR:
    case WM_SYSDEADCHAR:
    case WM_CHAR:
    case WM_SYSCHAR: {
      const Win32Message message =
          Win32Message{.action = action, .wparam = wparam, .lparam = lparam};
      current_session_.push_back(message);

      char32_t code_point;
      if (message.IsHighSurrogate()) {
        // A high surrogate is always followed by a low surrogate.  Process the
        // session later and consider this message as handled.
        return true;
      } else if (message.IsLowSurrogate()) {
        const Win32Message* last_message =
            current_session_.size() <= 1
                ? nullptr
                : &current_session_[current_session_.size() - 2];
        if (last_message == nullptr || !last_message->IsHighSurrogate()) {
          return false;
        }
        // A low surrogate always follows a high surrogate, marking the end of
        // a char session. Process the session after the if clause.
        code_point =
            CodePointFromSurrogatePair(last_message->wparam, message.wparam);
      } else {
        // A non-surrogate character always appears alone. Process the session
        // after the if clause.
        code_point = static_cast<wchar_t>(message.wparam);
      }

      // If this char message is preceded by a key down message, then dispatch
      // the key down message as a key down event first, and only dispatch the
      // OnText if the key down event is not handled.
      if (current_session_.front().IsGeneralKeyDown()) {
        const Win32Message first_message = current_session_.front();
        const uint8_t scancode = (lparam >> 16) & 0xff;
        const uint16_t key_code = first_message.wparam;
        const bool extended = ((lparam >> 24) & 0x01) == 0x01;
        const bool was_down = lparam & 0x40000000;
        // Certain key combinations yield control characters as WM_CHAR's
        // lParam. For example, 0x01 for Ctrl-A. Filter these characters. See
        // https://docs.microsoft.com/en-us/windows/win32/learnwin32/accelerator-tables
        char32_t character;
        if (action == WM_DEADCHAR || action == WM_SYSDEADCHAR) {
          // Mask the resulting char with kDeadKeyCharMask anyway, because in
          // rare cases the bit is *not* set (US INTL Shift-6 circumflex, see
          // https://github.com/flutter/flutter/issues/92654 .)
          character =
              window_delegate_->Win32MapVkToChar(key_code) | kDeadKeyCharMask;
        } else {
          character = IsPrintable(code_point) ? code_point : 0;
        }
        auto event = std::make_unique<PendingEvent>(PendingEvent{
            .key = key_code,
            .scancode = scancode,
            .action = static_cast<UINT>(action == WM_SYSCHAR ? WM_SYSKEYDOWN
                                                             : WM_KEYDOWN),
            .character = character,
            .extended = extended,
            .was_down = was_down,
            .session = std::move(current_session_),
        });

        pending_events_.push_back(std::move(event));
        ProcessNextEvent();

        // SYS messages must not be consumed by `HandleMessage` so that they are
        // forwarded to the system.
        return !IsSysAction(action);
      }

      // If the charcter session is not preceded by a key down message,
      // mark PendingEvent::action as WM_CHAR, informing |PerformProcessEvent|
      // to dispatch the text content immediately.
      //
      // Only WM_CHAR should be treated as characters. WM_SYS*CHAR are not part
      // of text input, and WM_DEADCHAR will be incorporated into a later
      // WM_CHAR with the full character.
      if (action == WM_CHAR) {
        auto event = std::make_unique<PendingEvent>(PendingEvent{
            .action = WM_CHAR,
            .character = code_point,
            .session = std::move(current_session_),
        });
        pending_events_.push_back(std::move(event));
        ProcessNextEvent();
      }
      return true;
    }

    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
    case WM_KEYUP:
    case WM_SYSKEYUP: {
      if (wparam == VK_PACKET) {
        return false;
      }

      const uint8_t scancode = (lparam >> 16) & 0xff;
      const bool extended = ((lparam >> 24) & 0x01) == 0x01;
      // If the key is a modifier, get its side.
      const uint16_t key_code = ResolveKeyCode(wparam, extended, scancode);
      const bool was_down = lparam & 0x40000000;

      // Detect a pattern of key events in order to forge a CtrlLeft up event.
      // See |IsKeyDownAltRight| for explanation.
      if (IsKeyDownAltRight(action, key_code, extended)) {
        if (last_key_is_ctrl_left_down) {
          should_synthesize_ctrl_left_up = true;
        }
      }
      if (IsKeyDownCtrlLeft(action, key_code)) {
        last_key_is_ctrl_left_down = true;
        ctrl_left_scancode = scancode;
        should_synthesize_ctrl_left_up = false;
      } else {
        last_key_is_ctrl_left_down = false;
      }
      if (IsKeyUpAltRight(action, key_code, extended)) {
        if (should_synthesize_ctrl_left_up) {
          should_synthesize_ctrl_left_up = false;
          const LPARAM lParam =
              (1 /* repeat_count */ << 0) | (ctrl_left_scancode << 16) |
              (0 /* extended */ << 24) | (1 /* prev_state */ << 30) |
              (1 /* transition */ << 31);
          window_delegate_->Win32DispatchMessage(WM_KEYUP, VK_CONTROL, lParam);
        }
      }

      current_session_.clear();
      current_session_.push_back(
          Win32Message{.action = action, .wparam = wparam, .lparam = lparam});
      const bool is_keydown_message =
          (action == WM_KEYDOWN || action == WM_SYSKEYDOWN);
      // Check if this key produces a character by peeking if this key down
      // message has a following char message. Certain key messages are not
      // followed by char messages even though `MapVirtualKey` returns a valid
      // character (such as Ctrl + Digit, see
      // https://github.com/flutter/flutter/issues/85587 ).
      unsigned int character = window_delegate_->Win32MapVkToChar(wparam);
      UINT next_key_action = PeekNextMessageType(WM_KEYFIRST, WM_KEYLAST);
      bool has_char_action =
          (next_key_action == WM_DEADCHAR ||
           next_key_action == WM_SYSDEADCHAR || next_key_action == WM_CHAR ||
           next_key_action == WM_SYSCHAR);
      if (character > 0 && is_keydown_message && has_char_action) {
        // This key down message has a following char message. Process this
        // session in the char message, because the character for the key call
        // should be decided by the char events. Consider this message as
        // handled.
        return true;
      }

      // This key down message is not followed by a char message. Conclude this
      // session.
      auto event = std::make_unique<PendingEvent>(PendingEvent{
          .key = key_code,
          .scancode = scancode,
          .action = action,
          .character = 0,
          .extended = extended,
          .was_down = was_down,
          .session = std::move(current_session_),
      });
      pending_events_.push_back(std::move(event));
      ProcessNextEvent();
      // SYS messages must not be consumed by `HandleMessage` so that they are
      // forwarded to the system.
      return !IsSysAction(action);
    }
    default:
      assert(false);
  }
  return false;
}

void KeyboardManager::ProcessNextEvent() {
  if (processing_event_ || pending_events_.empty()) {
    return;
  }
  processing_event_ = true;
  auto pending_event = std::move(pending_events_.front());
  pending_events_.pop_front();
  PerformProcessEvent(std::move(pending_event), [this] {
    assert(processing_event_);
    processing_event_ = false;
    ProcessNextEvent();
  });
}

void KeyboardManager::PerformProcessEvent(std::unique_ptr<PendingEvent> event,
                                          std::function<void()> callback) {
  // PendingEvent::action being WM_CHAR means this is a char message without
  // a preceding key message, and should be dispatched immediately.
  if (event->action == WM_CHAR) {
    DispatchText(*event);
    callback();
    return;
  }

  // A unique_ptr can't be sent into a lambda without C++23's
  // move_only_function. Until then, `event` is sent as a raw pointer, hoping
  // WindowDelegate::OnKey to correctly call it once and only once.
  PendingEvent* event_p = event.release();
  window_delegate_->OnKey(
      event_p->key, event_p->scancode, event_p->action, event_p->character,
      event_p->extended, event_p->was_down,
      [this, event_p, callback = std::move(callback)](bool handled) {
        HandleOnKeyResult(std::unique_ptr<PendingEvent>(event_p), handled);
        callback();
      });
}

void KeyboardManager::HandleOnKeyResult(std::unique_ptr<PendingEvent> event,
                                        bool framework_handled) {
  const UINT last_action = event->session.back().action;
  // SYS messages must not be redispached, and their text content is not
  // dispatched either.
  bool handled = framework_handled || IsSysAction(last_action);

  if (handled) {
    return;
  }

  // Only WM_CHAR should be treated as characters. WM_SYS*CHAR are not part of
  // text input, and WM_DEADCHAR will be incorporated into a later WM_CHAR with
  // the full character.
  if (last_action == WM_CHAR) {
    DispatchText(*event);
  }

  RedispatchEvent(std::move(event));
}

void KeyboardManager::DispatchText(const PendingEvent& event) {
  // Check if the character is printable based on the last wparam, which works
  // even if the last wparam is a low surrogate, because the only unprintable
  // keys defined by `IsPrintable` are certain characters at lower ASCII range.
  // These ASCII control characters are sent as WM_CHAR events for all control
  // key shortcuts.
  assert(!event.session.empty());
  bool is_printable = IsPrintable(event.session.back().wparam);
  bool valid = event.character != 0 && is_printable;
  if (valid) {
    auto text = EncodeUtf16(event.character);
    window_delegate_->OnText(text);
  }
}

UINT KeyboardManager::PeekNextMessageType(UINT wMsgFilterMin,
                                          UINT wMsgFilterMax) {
  MSG next_message;
  BOOL has_msg = window_delegate_->Win32PeekMessage(
      &next_message, wMsgFilterMin, wMsgFilterMax, PM_NOREMOVE);
  if (!has_msg) {
    return 0;
  }
  return next_message.message;
}

}  // namespace flutter
