// 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 {

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

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

// Returns true if this key is a key down event of ShiftRight.
//
// This is a temporary solution to
// https://github.com/flutter/flutter/issues/81674, and forces ShiftRight
// KeyDown events to not be redispatched regardless of the framework's response.
//
// If a ShiftRight KeyDown event is not handled by the framework and is
// redispatched, Win32 will not send its following KeyUp event and keeps
// recording ShiftRight as being pressed.
static bool IsKeyDownShiftRight(int virtual_key, bool was_down) {
#ifdef WINUWP
  return false;
#else
  return virtual_key == VK_RSHIFT && !was_down;
#endif
}

// 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 synthesizes 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) {
#ifdef WINUWP
  return false;
#else
  return virtual_key == VK_RMENU && extended && action == WM_KEYDOWN;
#endif
}

// 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) {
#ifdef WINUWP
  return false;
#else
  return virtual_key == VK_RMENU && extended && action == WM_KEYUP;
#endif
}

// 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) {
#ifdef WINUWP
  return false;
#else
  return virtual_key == VK_LCONTROL && action == WM_KEYDOWN;
#endif
}

}  // namespace

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

KeyboardKeyHandler::KeyboardKeyHandler(EventDispatcher dispatch_event)
    : dispatch_event_(dispatch_event),
      last_sequence_id_(1),
      last_key_is_ctrl_left_down(false) {}

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::DispatchEvent(const PendingEvent& event) {
  // TODO(dkwingsmt) consider adding support for dispatching events for UWP
  // in order to support add-to-app.
  // https://github.com/flutter/flutter/issues/70202
#ifdef WINUWP
  return;
#else
  char32_t character = event.character;

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

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

void KeyboardKeyHandler::RedispatchEvent(std::unique_ptr<PendingEvent> event) {
#ifdef WINUWP
  return;
#else
  DispatchEvent(*event);
  pending_redispatches_.push_back(std::move(event));
#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;
  }

  if (IsKeyDownAltRight(action, key, extended)) {
    if (last_key_is_ctrl_left_down) {
      should_synthesize_ctrl_left_up = true;
    }
  }
  if (IsKeyDownCtrlLeft(action, key)) {
    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, extended)) {
    if (should_synthesize_ctrl_left_up) {
      should_synthesize_ctrl_left_up = false;
      PendingEvent ctrl_left_up{
          .key = VK_LCONTROL,
          .scancode = ctrl_left_scancode,
          .action = WM_KEYUP,
          .was_down = true,
      };
      DispatchEvent(ctrl_left_up);
    }
  }

  uint64_t sequence_id = ++last_sequence_id_;
  incoming->sequence_id = sequence_id;
  incoming->unreplied = delegates_.size();
  // There are a few situations where events must not be redispatched.
  // Initializing `any_handled` with true in such cases suffices, since it can
  // only be set to true and is used to disable redispatching.
  const bool must_not_redispatch = IsKeyDownShiftRight(key, was_down);
  incoming->any_handled = must_not_redispatch;

  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) {
        std::unique_ptr<PendingEvent> event_ptr = std::move(*iter);
        pending_responds_.erase(iter);
        // Don't dispatch handled events or dead key events.
        //
        // Redispatching dead keys events makes Win32 ignore the dead key state
        // and redispatches a normal character without combining it with the
        // next letter key.
        const bool should_redispatch =
            !event_ptr->any_handled && !_IsDeadKey(event_ptr->character);
        if (should_redispatch) {
          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
