///
/// @file KeyEvent.h
///
/// @brief The header for the KeyEvent class.
///
/// @author
///
/// This file is a part of Ultralight, a fast, lightweight, HTML UI engine
///
/// Website: <http://ultralig.ht>
///
/// Copyright (C) 2020 Ultralight, Inc. All rights reserved.
///
#pragma once
#include <Ultralight/Defines.h>
#include <Ultralight/KeyCodes.h>
#include <Ultralight/String.h>
#ifdef __OBJC__
#import <AppKit/NSEvent.h>
#endif

namespace ultralight {

///
/// @brief  A generic keyboard event that can be created from a platform event
///         or synthesized from scratch.
///
/// @see    View::FireKeyEvent
///
class UExport KeyEvent {
public:
  ///
  /// The various KeyEvent types.
  ///
  enum Type {
    ///
    /// Key-Down event type. (Does not trigger accelerator commands in WebCore)
    ///
    /// @NOTE: You should probably use RawKeyDown instead when a physical key
    ///        is pressed. This member is only here for historic compatibility
    ///        with WebCore's key event types.
    ///
    kType_KeyDown,

    ///
    /// Key-Up event type. Use this when a physical key is released.
    ///
    kType_KeyUp,

    ///
    /// Raw Key-Down type. Use this when a physical key is pressed.
    ///
    /// @NOTE: You should use RawKeyDown for physical key presses since it
    ///        allows WebCore to do additional command translation.
    ///
    kType_RawKeyDown,

    ///
    /// Character input event type. Use this when the OS generates text from
    /// a physical key being pressed (eg, WM_CHAR on Windows).
    ///
    kType_Char,
  };

  ///
  /// Creates an empty KeyEvent, you will need to initialize its members
  /// yourself. This is useful for synthesizing your own keyboard events.
  ///
  KeyEvent();

#ifdef _WIN32
  ///
  /// Create a KeyEvent directly from a Windows keyboard event.
  ///
  KeyEvent(Type type, uintptr_t wparam, intptr_t lparam, bool is_system_key);
#endif

#ifdef __OBJC__
  ///
  /// Create a KeyEvent directly from a macOS NSEvent.
  ///
  KeyEvent(NSEvent* evt);
#endif

  ///
  /// An enumeration of the different keyboard modifiers.
  ///
  enum Modifiers : uint8_t {
    /// Whether or not an ALT key is down
    kMod_AltKey = 1 << 0,

    /// Whether or not a Control key is down
    kMod_CtrlKey = 1 << 1,

    /// Whether or not a meta key (Command-key on Mac, Windows-key on Win) is down
    kMod_MetaKey = 1 << 2,

    /// Whether or not a Shift key is down
    kMod_ShiftKey = 1 << 3,
  };

  ///
  // The type of this KeyEvent
  ///
  Type type;

  ///
  /// The current state of the keyboard. Modifiers may be OR'd together to
  /// represent multiple values.
  ///
  unsigned modifiers;

  ///
  // The virtual key-code associated with this keyboard event. This is either
  // directly from the event (ie, WPARAM on Windows) or via a mapping function.
  // You can see a full list of the possible virtual key-codes in
  // KeyboardCodes.h
  ///
  int virtual_key_code;

  ///
  /// The actual key-code generated by the platform. The DOM spec primarily
  /// uses Windows-equivalent codes (hence virtualKeyCode above) but it helps to
  /// also specify the platform-specific key-code as well.
  ///
  int native_key_code;

  ///
  /// This is a string identifying the key that was pressed. This can be
  /// generated from the virtual_key_code via the GetKeyIdentifierFromVirtualKeyCode()
  /// utility function. You can find the full list of key identifiers at:
  ///   <http://www.w3.org/TR/DOM-Level-3-Events/keyset.html>
  ///
  String key_identifier;

  ///
  /// The actual text generated by this keyboard event. This is usually only a
  /// single character.
  ///
  String text;

  ///
  /// The text generated by this keyboard event before all modifiers except
  /// shift are applied. This is used internally for working out shortcut keys.
  /// This is usually only a single character.
  ///
  String unmodified_text;

  ///
  /// Whether or not this is a keypad event.
  ///
  bool is_keypad;

  ///
  /// Whether or not this was generated as the result of an auto-repeat
  /// (eg, holding down a key).
  ///
  bool is_auto_repeat;

  ///
  /// Whether or not the pressed key is a "system key". This is a Windows-only
  /// concept and should be "false" for all non-Windows platforms. For more
  /// information, see the following link:
  ///   <http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx>
  bool is_system_key;
};

///
/// Utility function for generating a key identifier string from a virtual
/// key-code.
///
/// @param  virtual_key_code       The virtual key-code to generate the key
///                                identifier from.
///
/// @param  key_identifier_result  The string to store the result in.
///
void UExport GetKeyIdentifierFromVirtualKeyCode(int virtual_key_code,
  String& key_identifier_result);

}  // namespace ultralight
