// 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/public/flutter_linux/fl_binary_messenger.h"
#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"

#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"

#include <gmodule.h>

// Added here to stop the compiler from optimizing this function away.
G_MODULE_EXPORT GType fl_binary_messenger_get_type();

G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark,
               fl_binary_messenger_codec_error)

G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl,
                     fl_binary_messenger_impl,
                     FL,
                     BINARY_MESSENGER_IMPL,
                     GObject)

G_DECLARE_FINAL_TYPE(FlBinaryMessengerResponseHandleImpl,
                     fl_binary_messenger_response_handle_impl,
                     FL,
                     BINARY_MESSENGER_RESPONSE_HANDLE_IMPL,
                     FlBinaryMessengerResponseHandle)

G_DEFINE_INTERFACE(FlBinaryMessenger, fl_binary_messenger, G_TYPE_OBJECT)

struct _FlBinaryMessengerImpl {
  GObject parent_instance;

  GWeakRef engine;

  // PlatformMessageHandler keyed by channel name.
  GHashTable* platform_message_handlers;
};

static void fl_binary_messenger_impl_iface_init(
    FlBinaryMessengerInterface* iface);

G_DEFINE_TYPE_WITH_CODE(
    FlBinaryMessengerImpl,
    fl_binary_messenger_impl,
    G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(),
                          fl_binary_messenger_impl_iface_init))

static void fl_binary_messenger_response_handle_class_init(
    FlBinaryMessengerResponseHandleClass* klass) {}

G_DEFINE_TYPE(FlBinaryMessengerResponseHandle,
              fl_binary_messenger_response_handle,
              G_TYPE_OBJECT)

static void fl_binary_messenger_response_handle_init(
    FlBinaryMessengerResponseHandle* self) {}

struct _FlBinaryMessengerResponseHandleImpl {
  FlBinaryMessengerResponseHandle parent_instance;

  // Messenger sending response on.
  FlBinaryMessengerImpl* messenger;

  // Handle to send the response with. This is cleared to nullptr when it is
  // used.
  const FlutterPlatformMessageResponseHandle* response_handle;
};

G_DEFINE_TYPE(FlBinaryMessengerResponseHandleImpl,
              fl_binary_messenger_response_handle_impl,
              fl_binary_messenger_response_handle_get_type())

static void fl_binary_messenger_default_init(
    FlBinaryMessengerInterface* iface) {}

static void fl_binary_messenger_response_handle_impl_dispose(GObject* object) {
  FlBinaryMessengerResponseHandleImpl* self =
      FL_BINARY_MESSENGER_RESPONSE_HANDLE_IMPL(object);

  g_autoptr(FlEngine) engine =
      FL_ENGINE(g_weak_ref_get(&self->messenger->engine));
  if (self->response_handle != nullptr && engine != nullptr) {
    g_critical("FlBinaryMessengerResponseHandle was not responded to");
  }

  g_clear_object(&self->messenger);
  self->response_handle = nullptr;

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

static void fl_binary_messenger_response_handle_impl_class_init(
    FlBinaryMessengerResponseHandleImplClass* klass) {
  G_OBJECT_CLASS(klass)->dispose =
      fl_binary_messenger_response_handle_impl_dispose;
}

static void fl_binary_messenger_response_handle_impl_init(
    FlBinaryMessengerResponseHandleImpl* self) {}

static FlBinaryMessengerResponseHandleImpl*
fl_binary_messenger_response_handle_impl_new(
    FlBinaryMessengerImpl* messenger,
    const FlutterPlatformMessageResponseHandle* response_handle) {
  FlBinaryMessengerResponseHandleImpl* self =
      FL_BINARY_MESSENGER_RESPONSE_HANDLE_IMPL(g_object_new(
          fl_binary_messenger_response_handle_impl_get_type(), nullptr));

  self->messenger = FL_BINARY_MESSENGER_IMPL(g_object_ref(messenger));
  self->response_handle = response_handle;

  return self;
}

typedef struct {
  FlBinaryMessengerMessageHandler message_handler;
  gpointer message_handler_data;
  GDestroyNotify message_handler_destroy_notify;
} PlatformMessageHandler;

static PlatformMessageHandler* platform_message_handler_new(
    FlBinaryMessengerMessageHandler handler,
    gpointer user_data,
    GDestroyNotify destroy_notify) {
  PlatformMessageHandler* self = static_cast<PlatformMessageHandler*>(
      g_malloc0(sizeof(PlatformMessageHandler)));
  self->message_handler = handler;
  self->message_handler_data = user_data;
  self->message_handler_destroy_notify = destroy_notify;
  return self;
}

static void platform_message_handler_free(gpointer data) {
  PlatformMessageHandler* self = static_cast<PlatformMessageHandler*>(data);
  if (self->message_handler_destroy_notify) {
    self->message_handler_destroy_notify(self->message_handler_data);
  }
  g_free(self);
}

static void engine_weak_notify_cb(gpointer user_data,
                                  GObject* where_the_object_was) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(user_data);

  // Disconnect any handlers.
  // Take the reference in case a handler tries to modify this table.
  g_autoptr(GHashTable) handlers = self->platform_message_handlers;
  self->platform_message_handlers = g_hash_table_new_full(
      g_str_hash, g_str_equal, g_free, platform_message_handler_free);
  g_hash_table_remove_all(handlers);
}

static gboolean fl_binary_messenger_platform_message_cb(
    FlEngine* engine,
    const gchar* channel,
    GBytes* message,
    const FlutterPlatformMessageResponseHandle* response_handle,
    void* user_data) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(user_data);

  PlatformMessageHandler* handler = static_cast<PlatformMessageHandler*>(
      g_hash_table_lookup(self->platform_message_handlers, channel));
  if (handler == nullptr) {
    return FALSE;
  }

  g_autoptr(FlBinaryMessengerResponseHandleImpl) handle =
      fl_binary_messenger_response_handle_impl_new(self, response_handle);
  handler->message_handler(FL_BINARY_MESSENGER(self), channel, message,
                           FL_BINARY_MESSENGER_RESPONSE_HANDLE(handle),
                           handler->message_handler_data);

  return TRUE;
}

static void fl_binary_messenger_impl_dispose(GObject* object) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(object);

  {
    g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
    if (engine) {
      g_object_weak_unref(G_OBJECT(engine), engine_weak_notify_cb, self);
    }
  }

  g_weak_ref_clear(&self->engine);

  g_clear_pointer(&self->platform_message_handlers, g_hash_table_unref);

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

static void set_message_handler_on_channel(
    FlBinaryMessenger* messenger,
    const gchar* channel,
    FlBinaryMessengerMessageHandler handler,
    gpointer user_data,
    GDestroyNotify destroy_notify) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger);

  // Don't set handlers if engine already gone.
  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
  if (engine == nullptr) {
    if (handler != nullptr) {
      g_warning(
          "Attempted to set message handler on an FlBinaryMessenger without an "
          "engine");
    }
    if (destroy_notify != nullptr) {
      destroy_notify(user_data);
    }
    return;
  }

  if (handler != nullptr) {
    g_hash_table_replace(
        self->platform_message_handlers, g_strdup(channel),
        platform_message_handler_new(handler, user_data, destroy_notify));
  } else {
    g_hash_table_remove(self->platform_message_handlers, channel);
  }
}

static gboolean do_unref(gpointer value) {
  g_object_unref(value);
  return G_SOURCE_REMOVE;
}

// Note: This function can be called from any thread.
static gboolean send_response(FlBinaryMessenger* messenger,
                              FlBinaryMessengerResponseHandle* response_handle_,
                              GBytes* response,
                              GError** error) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger);
  g_return_val_if_fail(
      FL_IS_BINARY_MESSENGER_RESPONSE_HANDLE_IMPL(response_handle_), FALSE);
  FlBinaryMessengerResponseHandleImpl* response_handle =
      FL_BINARY_MESSENGER_RESPONSE_HANDLE_IMPL(response_handle_);

  g_return_val_if_fail(response_handle->messenger == self, FALSE);
  g_return_val_if_fail(response_handle->response_handle != nullptr, FALSE);

  FlEngine* engine = FL_ENGINE(g_weak_ref_get(&self->engine));
  if (engine == nullptr) {
    return TRUE;
  }

  gboolean result = false;
  if (response_handle->response_handle == nullptr) {
    g_set_error(
        error, FL_BINARY_MESSENGER_ERROR,
        FL_BINARY_MESSENGER_ERROR_ALREADY_RESPONDED,
        "Attempted to respond to a message that is already responded to");
    result = FALSE;
  } else {
    result = fl_engine_send_platform_message_response(
        engine, response_handle->response_handle, response, error);
    response_handle->response_handle = nullptr;
  }

  // This guarantees that the dispose method for the engine is executed
  // on the platform thread in the rare chance this is the last ref.
  g_idle_add(do_unref, engine);

  return result;
}

static void platform_message_ready_cb(GObject* object,
                                      GAsyncResult* result,
                                      gpointer user_data) {
  GTask* task = G_TASK(user_data);
  g_task_return_pointer(task, result, g_object_unref);
}

static void send_on_channel(FlBinaryMessenger* messenger,
                            const gchar* channel,
                            GBytes* message,
                            GCancellable* cancellable,
                            GAsyncReadyCallback callback,
                            gpointer user_data) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger);

  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
  if (engine == nullptr) {
    return;
  }

  fl_engine_send_platform_message(
      engine, channel, message, cancellable,
      callback != nullptr ? platform_message_ready_cb : nullptr,
      callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
                          : nullptr);
}

static GBytes* send_on_channel_finish(FlBinaryMessenger* messenger,
                                      GAsyncResult* result,
                                      GError** error) {
  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(messenger);
  g_return_val_if_fail(g_task_is_valid(result, self), FALSE);

  g_autoptr(GTask) task = G_TASK(result);
  GAsyncResult* r = G_ASYNC_RESULT(g_task_propagate_pointer(task, nullptr));

  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
  if (engine == nullptr) {
    return nullptr;
  }

  return fl_engine_send_platform_message_finish(engine, r, error);
}

static void fl_binary_messenger_impl_class_init(
    FlBinaryMessengerImplClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_binary_messenger_impl_dispose;
}

static void fl_binary_messenger_impl_iface_init(
    FlBinaryMessengerInterface* iface) {
  iface->set_message_handler_on_channel = set_message_handler_on_channel;
  iface->send_response = send_response;
  iface->send_on_channel = send_on_channel;
  iface->send_on_channel_finish = send_on_channel_finish;
}

static void fl_binary_messenger_impl_init(FlBinaryMessengerImpl* self) {
  self->platform_message_handlers = g_hash_table_new_full(
      g_str_hash, g_str_equal, g_free, platform_message_handler_free);
}

FlBinaryMessenger* fl_binary_messenger_new(FlEngine* engine) {
  g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);

  FlBinaryMessengerImpl* self = FL_BINARY_MESSENGER_IMPL(
      g_object_new(fl_binary_messenger_impl_get_type(), nullptr));

  // Added to stop compiler complaining about an unused function.
  FL_IS_BINARY_MESSENGER_IMPL(self);

  g_weak_ref_init(&self->engine, G_OBJECT(engine));
  g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, self);

  fl_engine_set_platform_message_handler(
      engine, fl_binary_messenger_platform_message_cb, self, NULL);

  return FL_BINARY_MESSENGER(self);
}

G_MODULE_EXPORT void fl_binary_messenger_set_message_handler_on_channel(
    FlBinaryMessenger* self,
    const gchar* channel,
    FlBinaryMessengerMessageHandler handler,
    gpointer user_data,
    GDestroyNotify destroy_notify) {
  g_return_if_fail(FL_IS_BINARY_MESSENGER(self));
  g_return_if_fail(channel != nullptr);

  FL_BINARY_MESSENGER_GET_IFACE(self)->set_message_handler_on_channel(
      self, channel, handler, user_data, destroy_notify);
}

// Note: This function can be called from any thread.
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(
    FlBinaryMessenger* self,
    FlBinaryMessengerResponseHandle* response_handle,
    GBytes* response,
    GError** error) {
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(self), FALSE);
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle),
                       FALSE);

  return FL_BINARY_MESSENGER_GET_IFACE(self)->send_response(
      self, response_handle, response, error);
}

G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(
    FlBinaryMessenger* self,
    const gchar* channel,
    GBytes* message,
    GCancellable* cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data) {
  g_return_if_fail(FL_IS_BINARY_MESSENGER(self));
  g_return_if_fail(channel != nullptr);

  FL_BINARY_MESSENGER_GET_IFACE(self)->send_on_channel(
      self, channel, message, cancellable, callback, user_data);
}

G_MODULE_EXPORT GBytes* fl_binary_messenger_send_on_channel_finish(
    FlBinaryMessenger* self,
    GAsyncResult* result,
    GError** error) {
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(self), FALSE);

  return FL_BINARY_MESSENGER_GET_IFACE(self)->send_on_channel_finish(
      self, result, error);
}
