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

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

#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_method_codec.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"

static constexpr char kChannelName[] = "flutter/platform";
static constexpr char kBadArgumentsError[] = "Bad Arguments";
static constexpr char kUnknownClipboardFormatError[] =
    "Unknown Clipboard Format";
static constexpr char kInProgressError[] = "In Progress";
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
static constexpr char kClipboardHasStringsMethod[] = "Clipboard.hasStrings";
static constexpr char kExitApplicationMethod[] = "System.exitApplication";
static constexpr char kRequestAppExitMethod[] = "System.requestAppExit";
static constexpr char kInitializationCompleteMethod[] =
    "System.initializationComplete";
static constexpr char kPlaySoundMethod[] = "SystemSound.play";
static constexpr char kSystemNavigatorPopMethod[] = "SystemNavigator.pop";
static constexpr char kTextKey[] = "text";
static constexpr char kValueKey[] = "value";

static constexpr char kExitTypeKey[] = "type";
static constexpr char kExitTypeCancelable[] = "cancelable";
static constexpr char kExitTypeRequired[] = "required";

static constexpr char kExitResponseKey[] = "response";
static constexpr char kExitResponseCancel[] = "cancel";
static constexpr char kExitResponseExit[] = "exit";

static constexpr char kTextPlainFormat[] = "text/plain";

static constexpr char kSoundTypeAlert[] = "SystemSoundType.alert";
static constexpr char kSoundTypeClick[] = "SystemSoundType.click";

struct _FlPlatformPlugin {
  GObject parent_instance;

  FlMethodChannel* channel;
  FlMethodCall* exit_application_method_call;
  GCancellable* cancellable;
  bool app_initialization_complete;
};

G_DEFINE_TYPE(FlPlatformPlugin, fl_platform_plugin, G_TYPE_OBJECT)

// Sends the method call response to Flutter.
static void send_response(FlMethodCall* method_call,
                          FlMethodResponse* response) {
  g_autoptr(GError) error = nullptr;
  if (!fl_method_call_respond(method_call, response, &error)) {
    g_warning("Failed to send method call response: %s", error->message);
  }
}

// Called when clipboard text received.
static void clipboard_text_cb(GtkClipboard* clipboard,
                              const gchar* text,
                              gpointer user_data) {
  g_autoptr(FlMethodCall) method_call = FL_METHOD_CALL(user_data);

  g_autoptr(FlValue) result = nullptr;
  if (text != nullptr) {
    result = fl_value_new_map();
    fl_value_set_string_take(result, kTextKey, fl_value_new_string(text));
  }

  g_autoptr(FlMethodResponse) response =
      FL_METHOD_RESPONSE(fl_method_success_response_new(result));
  send_response(method_call, response);
}

// Called when clipboard text received during has_strings.
static void clipboard_text_has_strings_cb(GtkClipboard* clipboard,
                                          const gchar* text,
                                          gpointer user_data) {
  g_autoptr(FlMethodCall) method_call = FL_METHOD_CALL(user_data);

  g_autoptr(FlValue) result = fl_value_new_map();
  fl_value_set_string_take(
      result, kValueKey,
      fl_value_new_bool(text != nullptr && strlen(text) > 0));

  g_autoptr(FlMethodResponse) response =
      FL_METHOD_RESPONSE(fl_method_success_response_new(result));
  send_response(method_call, response);
}

// Called when Flutter wants to copy to the clipboard.
static FlMethodResponse* clipboard_set_data(FlPlatformPlugin* self,
                                            FlValue* args) {
  if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Argument map missing or malformed", nullptr));
  }

  FlValue* text_value = fl_value_lookup_string(args, kTextKey);
  if (text_value == nullptr ||
      fl_value_get_type(text_value) != FL_VALUE_TYPE_STRING) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Missing clipboard text", nullptr));
  }

  GtkClipboard* clipboard =
      gtk_clipboard_get_default(gdk_display_get_default());
  gtk_clipboard_set_text(clipboard, fl_value_get_string(text_value), -1);

  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}

// Called when Flutter wants to paste from the clipboard.
static FlMethodResponse* clipboard_get_data_async(FlPlatformPlugin* self,
                                                  FlMethodCall* method_call) {
  FlValue* args = fl_method_call_get_args(method_call);

  if (fl_value_get_type(args) != FL_VALUE_TYPE_STRING) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Expected string", nullptr));
  }

  const gchar* format = fl_value_get_string(args);
  if (strcmp(format, kTextPlainFormat) != 0) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kUnknownClipboardFormatError, "GTK clipboard API only supports text",
        nullptr));
  }

  GtkClipboard* clipboard =
      gtk_clipboard_get_default(gdk_display_get_default());
  gtk_clipboard_request_text(clipboard, clipboard_text_cb,
                             g_object_ref(method_call));

  // Will respond later.
  return nullptr;
}

// Called when Flutter wants to know if the content of the clipboard is able to
// be pasted, without actually accessing the clipboard content itself.
static FlMethodResponse* clipboard_has_strings_async(
    FlPlatformPlugin* self,
    FlMethodCall* method_call) {
  GtkClipboard* clipboard =
      gtk_clipboard_get_default(gdk_display_get_default());
  gtk_clipboard_request_text(clipboard, clipboard_text_has_strings_cb,
                             g_object_ref(method_call));

  // Will respond later.
  return nullptr;
}

// Get the exit response from a System.requestAppExit method call.
static gchar* get_exit_response(FlMethodResponse* response) {
  if (response == nullptr) {
    return nullptr;
  }

  g_autoptr(GError) error = nullptr;
  FlValue* result = fl_method_response_get_result(response, &error);
  if (result == nullptr) {
    g_warning("Error returned from System.requestAppExit: %s", error->message);
    return nullptr;
  }
  if (fl_value_get_type(result) != FL_VALUE_TYPE_MAP) {
    g_warning("System.requestAppExit result argument map missing or malformed");
    return nullptr;
  }

  FlValue* response_value = fl_value_lookup_string(result, kExitResponseKey);
  if (fl_value_get_type(response_value) != FL_VALUE_TYPE_STRING) {
    g_warning("Invalid response from System.requestAppExit");
    return nullptr;
  }
  return g_strdup(fl_value_get_string(response_value));
}

// Quit this application
static void quit_application() {
  GApplication* app = g_application_get_default();
  if (app == nullptr) {
    // Unable to gracefully quit, so just exit the process.
    exit(0);
  } else {
    g_application_quit(app);
  }
}

// Handle response of System.requestAppExit.
static void request_app_exit_response_cb(GObject* object,
                                         GAsyncResult* result,
                                         gpointer user_data) {
  FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(user_data);

  g_autoptr(GError) error = nullptr;
  g_autoptr(FlMethodResponse) method_response =
      fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), result,
                                             &error);
  g_autofree gchar* exit_response = nullptr;
  if (method_response == nullptr) {
    if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
      return;
    }
    g_warning("Failed to complete System.requestAppExit: %s", error->message);
  } else {
    exit_response = get_exit_response(method_response);
  }
  // If something went wrong, then just exit.
  if (exit_response == nullptr) {
    exit_response = g_strdup(kExitResponseExit);
  }

  if (g_str_equal(exit_response, kExitResponseExit)) {
    quit_application();
  } else if (g_str_equal(exit_response, kExitResponseCancel)) {
    // Canceled - no action to take.
  }

  // If request was due to a request from Flutter, pass result back.
  if (self->exit_application_method_call != nullptr) {
    g_autoptr(FlValue) exit_result = fl_value_new_map();
    fl_value_set_string_take(exit_result, kExitResponseKey,
                             fl_value_new_string(exit_response));
    g_autoptr(FlMethodResponse) exit_response =
        FL_METHOD_RESPONSE(fl_method_success_response_new(exit_result));
    if (!fl_method_call_respond(self->exit_application_method_call,
                                exit_response, &error)) {
      g_warning("Failed to send response to System.exitApplication: %s",
                error->message);
    }
    g_clear_object(&self->exit_application_method_call);
  }
}

// Send a request to Flutter to exit the application, but only if it's ready for
// a request.
static void request_app_exit(FlPlatformPlugin* self, const char* type) {
  g_autoptr(FlValue) args = fl_value_new_map();
  if (!self->app_initialization_complete ||
      g_str_equal(type, kExitTypeRequired)) {
    quit_application();
    return;
  }

  fl_value_set_string_take(args, kExitTypeKey, fl_value_new_string(type));
  fl_method_channel_invoke_method(self->channel, kRequestAppExitMethod, args,
                                  self->cancellable,
                                  request_app_exit_response_cb, self);
}

// Called when the Dart app has finished initialization and is ready to handle
// requests. For the Flutter framework, this means after the ServicesBinding has
// been initialized and it sends a System.initializationComplete message.
static FlMethodResponse* system_intitialization_complete(
    FlPlatformPlugin* self,
    FlMethodCall* method_call) {
  self->app_initialization_complete = TRUE;
  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}

// Called when Flutter wants to exit the application.
static FlMethodResponse* system_exit_application(FlPlatformPlugin* self,
                                                 FlMethodCall* method_call) {
  FlValue* args = fl_method_call_get_args(method_call);
  if (fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Argument map missing or malformed", nullptr));
  }

  FlValue* type_value = fl_value_lookup_string(args, kExitTypeKey);
  if (type_value == nullptr ||
      fl_value_get_type(type_value) != FL_VALUE_TYPE_STRING) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Missing type argument", nullptr));
  }
  const char* type = fl_value_get_string(type_value);

  // Save method call to respond to when our request to Flutter completes.
  if (self->exit_application_method_call != nullptr) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kInProgressError, "Request already in progress", nullptr));
  }
  self->exit_application_method_call =
      FL_METHOD_CALL(g_object_ref(method_call));

  // Requested to immediately quit if the app hasn't yet signaled that it is
  // ready to handle requests, or if the type of exit requested is "required".
  if (!self->app_initialization_complete ||
      g_str_equal(type, kExitTypeRequired)) {
    quit_application();
    g_autoptr(FlValue) exit_result = fl_value_new_map();
    fl_value_set_string_take(exit_result, kExitResponseKey,
                             fl_value_new_string(kExitResponseExit));
    return FL_METHOD_RESPONSE(fl_method_success_response_new(exit_result));
  }

  // Send the request back to Flutter to follow the standard process.
  request_app_exit(self, type);

  // Will respond later.
  return nullptr;
}

// Called when Flutter wants to play a sound.
static FlMethodResponse* system_sound_play(FlPlatformPlugin* self,
                                           FlValue* args) {
  if (fl_value_get_type(args) != FL_VALUE_TYPE_STRING) {
    return FL_METHOD_RESPONSE(fl_method_error_response_new(
        kBadArgumentsError, "Expected string", nullptr));
  }

  const gchar* type = fl_value_get_string(args);
  if (strcmp(type, kSoundTypeAlert) == 0) {
    GdkDisplay* display = gdk_display_get_default();
    if (display != nullptr) {
      gdk_display_beep(display);
    }
  } else if (strcmp(type, kSoundTypeClick) == 0) {
    // We don't make sounds for keyboard on desktops.
  } else {
    g_warning("Ignoring unknown sound type %s in SystemSound.play.\n", type);
  }

  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}

// Called when Flutter wants to quit the application.
static FlMethodResponse* system_navigator_pop(FlPlatformPlugin* self) {
  quit_application();
  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
}

// Called when a method call is received from Flutter.
static void method_call_cb(FlMethodChannel* channel,
                           FlMethodCall* method_call,
                           gpointer user_data) {
  FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(user_data);

  const gchar* method = fl_method_call_get_name(method_call);
  FlValue* args = fl_method_call_get_args(method_call);

  g_autoptr(FlMethodResponse) response = nullptr;
  if (strcmp(method, kSetClipboardDataMethod) == 0) {
    response = clipboard_set_data(self, args);
  } else if (strcmp(method, kGetClipboardDataMethod) == 0) {
    response = clipboard_get_data_async(self, method_call);
  } else if (strcmp(method, kClipboardHasStringsMethod) == 0) {
    response = clipboard_has_strings_async(self, method_call);
  } else if (strcmp(method, kExitApplicationMethod) == 0) {
    response = system_exit_application(self, method_call);
  } else if (strcmp(method, kInitializationCompleteMethod) == 0) {
    response = system_intitialization_complete(self, method_call);
  } else if (strcmp(method, kPlaySoundMethod) == 0) {
    response = system_sound_play(self, args);
  } else if (strcmp(method, kSystemNavigatorPopMethod) == 0) {
    response = system_navigator_pop(self);
  } else {
    response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
  }

  if (response != nullptr) {
    send_response(method_call, response);
  }
}

static void fl_platform_plugin_dispose(GObject* object) {
  FlPlatformPlugin* self = FL_PLATFORM_PLUGIN(object);

  g_cancellable_cancel(self->cancellable);

  g_clear_object(&self->channel);
  g_clear_object(&self->exit_application_method_call);
  g_clear_object(&self->cancellable);

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

static void fl_platform_plugin_class_init(FlPlatformPluginClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_platform_plugin_dispose;
}

static void fl_platform_plugin_init(FlPlatformPlugin* self) {
  self->cancellable = g_cancellable_new();
}

FlPlatformPlugin* fl_platform_plugin_new(FlBinaryMessenger* messenger) {
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);

  FlPlatformPlugin* self =
      FL_PLATFORM_PLUGIN(g_object_new(fl_platform_plugin_get_type(), nullptr));

  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
  self->channel =
      fl_method_channel_new(messenger, kChannelName, FL_METHOD_CODEC(codec));
  fl_method_channel_set_method_call_handler(self->channel, method_call_cb, self,
                                            nullptr);
  self->app_initialization_complete = FALSE;

  return self;
}

void fl_platform_plugin_request_app_exit(FlPlatformPlugin* self) {
  g_return_if_fail(FL_IS_PLATFORM_PLUGIN(self));
  // Request a cancellable exit.
  request_app_exit(self, kExitTypeCancelable);
}
