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

#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_

#include <functional>
#include <map>
#include <memory>
#include <string>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/keyboard_key_handler.h"

namespace flutter {

// Encode a 32-bit unicode code point into a UTF-8 byte array.
//
// See https://en.wikipedia.org/wiki/UTF-8#Encoding for the algorithm.
std::string ConvertChar32ToUtf8(char32_t ch);

// A delegate of |KeyboardKeyHandler| that handles events by sending
// converted |FlutterKeyEvent|s through the embedder API.
//
// This class communicates with the HardwareKeyboard API in the framework.
//
// Every key event must result in at least one FlutterKeyEvent, even an empty
// one (both logical and physical IDs are 0). This ensures that raw key
// messages are always preceded by key data so that the transit mode is
// correctly inferred. (Technically only the first key event needs so, but for
// simplicity.)
class KeyboardKeyEmbedderHandler
    : public KeyboardKeyHandler::KeyboardKeyHandlerDelegate {
 public:
  using SendEventHandler =
      std::function<void(const FlutterKeyEvent& /* event */,
                         FlutterKeyEventCallback /* callback */,
                         void* /* user_data */)>;
  using GetKeyStateHandler = std::function<SHORT(int /* nVirtKey */)>;
  using MapVirtualKeyToScanCode =
      std::function<SHORT(UINT /* nVirtKey */, bool /* extended */)>;

  // Build a KeyboardKeyEmbedderHandler.
  //
  // Use `send_event` to define how the class should dispatch converted
  // flutter events, as well as how to receive the response, to the engine. It's
  // typically FlutterWindowsEngine::SendKeyEvent. The 2nd and 3rd parameter
  // of the SendEventHandler call might be nullptr.
  //
  // Use `get_key_state` to define how the class should get a reliable result of
  // the state for a virtual key. It's typically Win32's GetKeyState, but can
  // also be nullptr (for UWP).
  //
  // Use `map_vk_to_scan` to define how the class should get map a virtual key
  // to a scan code. It's typically Win32's MapVirtualKey, but can also be
  // nullptr (for UWP).
  explicit KeyboardKeyEmbedderHandler(SendEventHandler send_event,
                                      GetKeyStateHandler get_key_state,
                                      MapVirtualKeyToScanCode map_vk_to_scan);

  virtual ~KeyboardKeyEmbedderHandler();

  // |KeyboardHandlerBase|
  void KeyboardHook(int key,
                    int scancode,
                    int action,
                    char32_t character,
                    bool extended,
                    bool was_down,
                    std::function<void(bool)> callback) override;

 private:
  struct PendingResponse {
    std::function<void(bool, uint64_t)> callback;
    uint64_t response_id;
  };

  // The information for a virtual key that's important enough that its
  // state is checked after every event.
  struct CriticalKey {
    // Last seen value of physical key and logical key for the virtual key.
    //
    // Used to synthesize down events.
    uint64_t physical_key;
    uint64_t logical_key;

    // Whether to ensure the pressing state of the key (usually for modifier
    // keys).
    bool check_pressed;
    // Whether to ensure the toggled state of the key (usually for lock keys).
    //
    // If this is true, `check_pressed` must be true.
    bool check_toggled;
    // Whether the lock key is currently toggled on.
    bool toggled_on;
  };

  // Implements the core logic of |KeyboardHook|, leaving out some state
  // guards.
  void KeyboardHookImpl(int key,
                        int scancode,
                        int action,
                        char32_t character,
                        bool extended,
                        bool was_down,
                        std::function<void(bool)> callback);

  // Assign |critical_keys_| with basic information.
  void InitCriticalKeys(MapVirtualKeyToScanCode map_virtual_key_to_scan_code);
  // Update |critical_keys_| with last seen logical and physical key.
  void UpdateLastSeenCritialKey(int virtual_key,
                                uint64_t physical_key,
                                uint64_t logical_key);
  // Check each key's state from |get_key_state_| and synthesize events
  // if their toggling states have been desynchronized.
  void SynchronizeCritialToggledStates(int event_virtual_key,
                                       bool is_event_down);
  // Check each key's state from |get_key_state_| and synthesize events
  // if their pressing states have been desynchronized.
  void SynchronizeCritialPressedStates(int event_virtual_key,
                                       int event_physical_key,
                                       bool is_event_down);

  // Wraps perform_send_event_ with state tracking. Use this instead of
  // |perform_send_event_| to send events to the framework.
  void SendEvent(const FlutterKeyEvent& event,
                 FlutterKeyEventCallback callback,
                 void* user_data);

  std::function<void(const FlutterKeyEvent&, FlutterKeyEventCallback, void*)>
      perform_send_event_;
  GetKeyStateHandler get_key_state_;

  // A map from physical keys to logical keys, each entry indicating a pressed
  // key.
  std::map<uint64_t, uint64_t> pressingRecords_;
  // Information for key events that have been sent to the framework but yet
  // to receive the response. Indexed by response IDs.
  std::map<uint64_t, std::unique_ptr<PendingResponse>> pending_responses_;
  // A self-incrementing integer, used as the ID for the next entry for
  // |pending_responses_|.
  uint64_t response_id_;
  // Whether any events has been sent with |PerformSendEvent| during a
  // |KeyboardHook|.
  bool sent_any_events;

  // Important keys whose states are checked and guaranteed synchronized
  // on every key event.
  //
  // The following maps map Win32 virtual key to the physical key and logical
  // key they're last seen.
  std::map<UINT, CriticalKey> critical_keys_;

  static uint64_t GetPhysicalKey(int scancode, bool extended);
  static uint64_t GetLogicalKey(int key, bool extended, int scancode);
  static void HandleResponse(bool handled, void* user_data);
  static void ConvertUtf32ToUtf8_(char* out, char32_t ch);
  static FlutterKeyEvent SynthesizeSimpleEvent(FlutterKeyEventType type,
                                               uint64_t physical,
                                               uint64_t logical,
                                               const char* character);
  static uint64_t ApplyPlaneToId(uint64_t id, uint64_t plane);

  static std::map<uint64_t, uint64_t> windowsToPhysicalMap_;
  static std::map<uint64_t, uint64_t> windowsToLogicalMap_;
  static std::map<uint64_t, uint64_t> scanCodeToLogicalMap_;

  // Mask for the 32-bit value portion of the key code.
  static const uint64_t valueMask;

  // The plane value for keys which have a Unicode representation.
  static const uint64_t unicodePlane;

  // The plane value for the private keys defined by the GTK embedding.
  static const uint64_t windowsPlane;
};

}  // namespace flutter

#endif  // FLUTTER_SHELL_PLATFORM_WINDOWS_KEYBOARD_KEY_EMBEDDER_HANDLER_H_
