// 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/linux/fl_key_channel_responder.h"

#include <gtk/gtk.h>
#include <cinttypes>

#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"

static constexpr char kChannelName[] = "flutter/keyevent";
static constexpr char kTypeKey[] = "type";
static constexpr char kTypeValueUp[] = "keyup";
static constexpr char kTypeValueDown[] = "keydown";
static constexpr char kKeymapKey[] = "keymap";
static constexpr char kKeyCodeKey[] = "keyCode";
static constexpr char kScanCodeKey[] = "scanCode";
static constexpr char kModifiersKey[] = "modifiers";
static constexpr char kToolkitKey[] = "toolkit";
static constexpr char kUnicodeScalarValuesKey[] = "unicodeScalarValues";

static constexpr char kGtkToolkit[] = "gtk";
static constexpr char kLinuxKeymap[] = "linux";

/* Declare and define FlKeyChannelUserData */

/**
 * FlKeyChannelUserData:
 * The user_data used when #FlKeyChannelResponder sends message through the
 * channel.
 */
G_DECLARE_FINAL_TYPE(FlKeyChannelUserData,
                     fl_key_channel_user_data,
                     FL,
                     KEY_CHANNEL_USER_DATA,
                     GObject);

struct _FlKeyChannelUserData {
  GObject parent_instance;

  // The current responder.
  FlKeyChannelResponder* responder;
  // The callback provided by the caller #FlKeyboardManager.
  FlKeyResponderAsyncCallback callback;
  // The user_data provided by the caller #FlKeyboardManager.
  gpointer user_data;
};

// Definition for FlKeyChannelUserData private class.
G_DEFINE_TYPE(FlKeyChannelUserData, fl_key_channel_user_data, G_TYPE_OBJECT)

// Dispose method for FlKeyChannelUserData private class.
static void fl_key_channel_user_data_dispose(GObject* object) {
  g_return_if_fail(FL_IS_KEY_CHANNEL_USER_DATA(object));
  FlKeyChannelUserData* self = FL_KEY_CHANNEL_USER_DATA(object);
  if (self->responder != nullptr) {
    g_object_remove_weak_pointer(
        G_OBJECT(self->responder),
        reinterpret_cast<gpointer*>(&(self->responder)));
    self->responder = nullptr;
  }
}

// Class initialization method for FlKeyChannelUserData private class.
static void fl_key_channel_user_data_class_init(
    FlKeyChannelUserDataClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_key_channel_user_data_dispose;
}

// Instance initialization method for FlKeyChannelUserData private class.
static void fl_key_channel_user_data_init(FlKeyChannelUserData* self) {}

// Creates a new FlKeyChannelUserData private class with all information.
//
// The callback and the user_data might be nullptr.
static FlKeyChannelUserData* fl_key_channel_user_data_new(
    FlKeyChannelResponder* responder,
    FlKeyResponderAsyncCallback callback,
    gpointer user_data) {
  FlKeyChannelUserData* self = FL_KEY_CHANNEL_USER_DATA(
      g_object_new(fl_key_channel_user_data_get_type(), nullptr));

  self->responder = responder;
  // Add a weak pointer so we can know if the key event responder disappeared
  // while the framework was responding.
  g_object_add_weak_pointer(G_OBJECT(responder),
                            reinterpret_cast<gpointer*>(&(self->responder)));
  self->callback = callback;
  self->user_data = user_data;
  return self;
}

/* Define FlKeyChannelResponder */

// Definition of the FlKeyChannelResponder GObject class.
struct _FlKeyChannelResponder {
  GObject parent_instance;

  FlBasicMessageChannel* channel;

  FlKeyChannelResponderMock* mock;
};

static void fl_key_channel_responder_iface_init(FlKeyResponderInterface* iface);

G_DEFINE_TYPE_WITH_CODE(
    FlKeyChannelResponder,
    fl_key_channel_responder,
    G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE(FL_TYPE_KEY_RESPONDER,
                          fl_key_channel_responder_iface_init))

static void fl_key_channel_responder_handle_event(
    FlKeyResponder* responder,
    FlKeyEvent* event,
    FlKeyResponderAsyncCallback callback,
    gpointer user_data);

static void fl_key_channel_responder_iface_init(
    FlKeyResponderInterface* iface) {
  iface->handle_event = fl_key_channel_responder_handle_event;
}

/* Implement FlKeyChannelResponder */

// Handles a response from the method channel to a key event sent to the
// framework earlier.
static void handle_response(GObject* object,
                            GAsyncResult* result,
                            gpointer user_data) {
  g_autoptr(FlKeyChannelUserData) data = FL_KEY_CHANNEL_USER_DATA(user_data);

  // Will also return if the weak pointer has been destroyed.
  if (data->responder == nullptr) {
    return;
  }

  FlKeyChannelResponder* self = data->responder;

  g_autoptr(GError) error = nullptr;
  FlBasicMessageChannel* messageChannel = FL_BASIC_MESSAGE_CHANNEL(object);
  FlValue* message =
      fl_basic_message_channel_send_finish(messageChannel, result, &error);
  if (self->mock != nullptr && self->mock->value_converter != nullptr) {
    message = self->mock->value_converter(message);
  }
  if (error != nullptr) {
    g_warning("Unable to retrieve framework response: %s", error->message);
    return;
  }
  g_autoptr(FlValue) handled_value = fl_value_lookup_string(message, "handled");
  bool handled = fl_value_get_bool(handled_value);

  data->callback(handled, data->user_data);
}

// Disposes of an FlKeyChannelResponder instance.
static void fl_key_channel_responder_dispose(GObject* object) {
  FlKeyChannelResponder* self = FL_KEY_CHANNEL_RESPONDER(object);

  g_clear_object(&self->channel);

  G_OBJECT_CLASS(fl_key_channel_responder_parent_class)->dispose(object);
}

// Initializes the FlKeyChannelResponder class methods.
static void fl_key_channel_responder_class_init(
    FlKeyChannelResponderClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_key_channel_responder_dispose;
}

// Initializes an FlKeyChannelResponder instance.
static void fl_key_channel_responder_init(FlKeyChannelResponder* self) {}

// Creates a new FlKeyChannelResponder instance, with a messenger used to send
// messages to the framework, and an FlTextInputPlugin that is used to handle
// key events that the framework doesn't handle. Mainly for testing purposes, it
// also takes an optional callback to call when a response is received, and an
// optional channel name to use when sending messages.
FlKeyChannelResponder* fl_key_channel_responder_new(
    FlBinaryMessenger* messenger,
    FlKeyChannelResponderMock* mock) {
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);

  FlKeyChannelResponder* self = FL_KEY_CHANNEL_RESPONDER(
      g_object_new(fl_key_channel_responder_get_type(), nullptr));
  self->mock = mock;

  g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
  const char* channel_name =
      mock == nullptr ? kChannelName : mock->channel_name;
  self->channel = fl_basic_message_channel_new(messenger, channel_name,
                                               FL_MESSAGE_CODEC(codec));

  return self;
}

// Sends a key event to the framework.
static void fl_key_channel_responder_handle_event(
    FlKeyResponder* responder,
    FlKeyEvent* event,
    FlKeyResponderAsyncCallback callback,
    gpointer user_data) {
  FlKeyChannelResponder* self = FL_KEY_CHANNEL_RESPONDER(responder);
  g_return_if_fail(event != nullptr);
  g_return_if_fail(callback != nullptr);

  const gchar* type = event->is_press ? kTypeValueDown : kTypeValueUp;
  int64_t scan_code = event->keycode;
  int64_t unicode_scarlar_values = gdk_keyval_to_unicode(event->keyval);

  // For most modifier keys, GTK keeps track of the "pressed" state of the
  // modifier keys. Flutter uses this information to keep modifier keys from
  // being "stuck" when a key-up event is lost because it happens after the app
  // loses focus.
  //
  // For Lock keys (ShiftLock, CapsLock, NumLock), however, GTK keeps track of
  // the state of the locks themselves, not the "pressed" state of the key.
  //
  // Since Flutter expects the "pressed" state of the modifier keys, the lock
  // state for these keys is discarded here, and it is substituted for the
  // pressed state of the key.
  //
  // This code has the flaw that if a key event is missed due to the app losing
  // focus, then this state will still think the key is pressed when it isn't,
  // but that is no worse than for "regular" keys until we implement the
  // sync/cancel events on app focus changes.
  //
  // This is necessary to do here instead of in the framework because Flutter
  // does modifier key syncing in the framework, and will turn on/off these keys
  // as being "pressed" whenever the lock is on, which breaks a lot of
  // interactions (for example, if shift-lock is on, tab traversal is broken).

  // Remove lock states from state mask.
  guint state = event->state & ~(GDK_LOCK_MASK | GDK_MOD2_MASK);

  static bool shift_lock_pressed = FALSE;
  static bool caps_lock_pressed = FALSE;
  static bool num_lock_pressed = FALSE;
  switch (event->keyval) {
    case GDK_KEY_Num_Lock:
      num_lock_pressed = event->is_press;
      break;
    case GDK_KEY_Caps_Lock:
      caps_lock_pressed = event->is_press;
      break;
    case GDK_KEY_Shift_Lock:
      shift_lock_pressed = event->is_press;
      break;
  }

  // Add back in the state matching the actual pressed state of the lock keys,
  // not the lock states.
  state |= (shift_lock_pressed || caps_lock_pressed) ? GDK_LOCK_MASK : 0x0;
  state |= num_lock_pressed ? GDK_MOD2_MASK : 0x0;

  g_autoptr(FlValue) message = fl_value_new_map();
  fl_value_set_string_take(message, kTypeKey, fl_value_new_string(type));
  fl_value_set_string_take(message, kKeymapKey,
                           fl_value_new_string(kLinuxKeymap));
  fl_value_set_string_take(message, kScanCodeKey, fl_value_new_int(scan_code));
  fl_value_set_string_take(message, kToolkitKey,
                           fl_value_new_string(kGtkToolkit));
  fl_value_set_string_take(message, kKeyCodeKey,
                           fl_value_new_int(event->keyval));
  fl_value_set_string_take(message, kModifiersKey, fl_value_new_int(state));
  if (unicode_scarlar_values != 0) {
    fl_value_set_string_take(message, kUnicodeScalarValuesKey,
                             fl_value_new_int(unicode_scarlar_values));
  }

  FlKeyChannelUserData* data =
      fl_key_channel_user_data_new(self, callback, user_data);
  // Send the message off to the framework for handling (or not).
  fl_basic_message_channel_send(self->channel, message, nullptr,
                                handle_response, data);
}
