// 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 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;
};

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.
static void request_app_exit(FlPlatformPlugin* self, const char* type) {
  g_autoptr(FlValue) args = fl_value_new_map();
  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 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 (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, 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);

  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);
}
