// 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 */)>;

  // 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).
  explicit KeyboardKeyEmbedderHandler(SendEventHandler send_event,
                                      GetKeyStateHandler get_key_state);

  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();
  // 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 this_virtual_key);
  // Check each key's state from |get_key_state_| and synthesize events
  // if their pressing states have been desynchronized.
  void SynchronizeCritialPressedStates();

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