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

#include "flutter/shell/platform/linux/fl_method_call_private.h"
#include "flutter/shell/platform/linux/fl_method_channel_private.h"
#include "flutter/shell/platform/linux/fl_method_codec_private.h"

#include <gmodule.h>

struct _FlMethodChannel {
  GObject parent_instance;

  // Messenger to communicate on
  FlBinaryMessenger* messenger;

  // Channel name
  gchar* name;

  // Codec to en/decode messages
  FlMethodCodec* codec;

  // Function called when a method call is received
  FlMethodChannelMethodCallHandler method_call_handler;
  gpointer method_call_handler_data;
};

// Added here to stop the compiler from optimising this function away
G_MODULE_EXPORT GType fl_method_channel_get_type();

G_DEFINE_TYPE(FlMethodChannel, fl_method_channel, G_TYPE_OBJECT)

// Called when a binary message is received on this channel
static void message_cb(FlBinaryMessenger* messenger,
                       const gchar* channel,
                       GBytes* message,
                       FlBinaryMessengerResponseHandle* response_handle,
                       gpointer user_data) {
  FlMethodChannel* self = FL_METHOD_CHANNEL(user_data);

  if (self->method_call_handler == nullptr)
    return;

  g_autofree gchar* method = nullptr;
  g_autoptr(FlValue) args = nullptr;
  g_autoptr(GError) error = nullptr;
  if (!fl_method_codec_decode_method_call(self->codec, message, &method, &args,
                                          &error)) {
    g_warning("Failed to decode method call: %s", error->message);
    return;
  }

  g_autoptr(FlMethodCall) method_call =
      fl_method_call_new(method, args, self, response_handle);
  self->method_call_handler(self, method_call, self->method_call_handler_data);
}

// Called when a response is received to a sent message
static void message_response_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 fl_method_channel_dispose(GObject* object) {
  FlMethodChannel* self = FL_METHOD_CHANNEL(object);

  if (self->messenger != nullptr)
    fl_binary_messenger_set_message_handler_on_channel(
        self->messenger, self->name, nullptr, nullptr);

  g_clear_object(&self->messenger);
  g_clear_pointer(&self->name, g_free);
  g_clear_object(&self->codec);

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

static void fl_method_channel_class_init(FlMethodChannelClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_method_channel_dispose;
}

static void fl_method_channel_init(FlMethodChannel* self) {}

G_MODULE_EXPORT FlMethodChannel* fl_method_channel_new(
    FlBinaryMessenger* messenger,
    const gchar* name,
    FlMethodCodec* codec) {
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER(messenger), nullptr);
  g_return_val_if_fail(name != nullptr, nullptr);
  g_return_val_if_fail(FL_IS_METHOD_CODEC(codec), nullptr);

  FlMethodChannel* self =
      FL_METHOD_CHANNEL(g_object_new(fl_method_channel_get_type(), nullptr));

  self->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
  self->name = g_strdup(name);
  self->codec = FL_METHOD_CODEC(g_object_ref(codec));

  fl_binary_messenger_set_message_handler_on_channel(
      self->messenger, self->name, message_cb, self);

  return self;
}

G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(
    FlMethodChannel* self,
    FlMethodChannelMethodCallHandler handler,
    gpointer user_data) {
  g_return_if_fail(FL_IS_METHOD_CHANNEL(self));

  self->method_call_handler = handler;
  self->method_call_handler_data = user_data;
}

G_MODULE_EXPORT void fl_method_channel_invoke_method(
    FlMethodChannel* self,
    const gchar* method,
    FlValue* args,
    GCancellable* cancellable,
    GAsyncReadyCallback callback,
    gpointer user_data) {
  g_return_if_fail(FL_IS_METHOD_CHANNEL(self));
  g_return_if_fail(method != nullptr);

  g_autoptr(GTask) task =
      callback != nullptr ? g_task_new(self, cancellable, callback, user_data)
                          : nullptr;

  g_autoptr(GError) error = nullptr;
  g_autoptr(GBytes) message =
      fl_method_codec_encode_method_call(self->codec, method, args, &error);
  if (message == nullptr) {
    if (task != nullptr)
      g_task_return_error(task, error);
    return;
  }

  fl_binary_messenger_send_on_channel(
      self->messenger, self->name, message, cancellable,
      callback != nullptr ? message_response_cb : nullptr,
      g_steal_pointer(&task));
}

G_MODULE_EXPORT FlMethodResponse* fl_method_channel_invoke_method_finish(
    FlMethodChannel* self,
    GAsyncResult* result,
    GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), nullptr);
  g_return_val_if_fail(g_task_is_valid(result, self), nullptr);

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

  g_autoptr(GBytes) response =
      fl_binary_messenger_send_on_channel_finish(self->messenger, r, error);
  if (response == nullptr)
    return nullptr;

  return fl_method_codec_decode_response(self->codec, response, error);
}

gboolean fl_method_channel_respond(
    FlMethodChannel* self,
    FlBinaryMessengerResponseHandle* response_handle,
    FlMethodResponse* response,
    GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CHANNEL(self), FALSE);
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle),
                       FALSE);
  g_return_val_if_fail(FL_IS_METHOD_SUCCESS_RESPONSE(response) ||
                           FL_IS_METHOD_ERROR_RESPONSE(response) ||
                           FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response),
                       FALSE);

  g_autoptr(GBytes) message = nullptr;
  if (FL_IS_METHOD_SUCCESS_RESPONSE(response)) {
    FlMethodSuccessResponse* r = FL_METHOD_SUCCESS_RESPONSE(response);
    message = fl_method_codec_encode_success_envelope(
        self->codec, fl_method_success_response_get_result(r), error);
  } else if (FL_IS_METHOD_ERROR_RESPONSE(response)) {
    FlMethodErrorResponse* r = FL_METHOD_ERROR_RESPONSE(response);
    message = fl_method_codec_encode_error_envelope(
        self->codec, fl_method_error_response_get_code(r),
        fl_method_error_response_get_message(r),
        fl_method_error_response_get_details(r), error);
  } else if (FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response))
    message = nullptr;
  else
    g_assert_not_reached();

  return fl_binary_messenger_send_response(self->messenger, response_handle,
                                           message, error);
}
