// 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_call.h"
#include "flutter/shell/platform/linux/fl_method_call_private.h"
#include "flutter/shell/platform/linux/fl_method_channel_private.h"

#include <gmodule.h>

struct _FlMethodCall {
  GObject parent_instance;

  // Name of method being called
  gchar* name;

  // Arguments provided to method call
  FlValue* args;

  // Channel to respond on
  FlMethodChannel* channel;
  FlBinaryMessengerResponseHandle* response_handle;
};

G_DEFINE_TYPE(FlMethodCall, fl_method_call, G_TYPE_OBJECT)

static void fl_method_call_dispose(GObject* object) {
  FlMethodCall* self = FL_METHOD_CALL(object);

  g_clear_pointer(&self->name, g_free);
  g_clear_pointer(&self->args, fl_value_unref);
  g_clear_object(&self->channel);
  g_clear_object(&self->response_handle);

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

static void fl_method_call_class_init(FlMethodCallClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_method_call_dispose;
}

static void fl_method_call_init(FlMethodCall* self) {}

FlMethodCall* fl_method_call_new(
    const gchar* name,
    FlValue* args,
    FlMethodChannel* channel,
    FlBinaryMessengerResponseHandle* response_handle) {
  g_return_val_if_fail(name != nullptr, nullptr);
  g_return_val_if_fail(args != nullptr, nullptr);
  g_return_val_if_fail(FL_IS_METHOD_CHANNEL(channel), nullptr);
  g_return_val_if_fail(FL_IS_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle),
                       nullptr);

  FlMethodCall* self =
      FL_METHOD_CALL(g_object_new(fl_method_call_get_type(), nullptr));

  self->name = g_strdup(name);
  self->args = fl_value_ref(args);
  self->channel = FL_METHOD_CHANNEL(g_object_ref(channel));
  self->response_handle =
      FL_BINARY_MESSENGER_RESPONSE_HANDLE(g_object_ref(response_handle));

  return self;
}

G_MODULE_EXPORT const gchar* fl_method_call_get_name(FlMethodCall* self) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), nullptr);
  return self->name;
}

G_MODULE_EXPORT FlValue* fl_method_call_get_args(FlMethodCall* self) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), nullptr);
  return self->args;
}

gboolean fl_method_call_respond(FlMethodCall* self,
                                FlMethodResponse* response,
                                GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), FALSE);
  g_return_val_if_fail(FL_IS_METHOD_RESPONSE(response), FALSE);
  return fl_method_channel_respond(self->channel, self->response_handle,
                                   response, error);
}

G_MODULE_EXPORT gboolean fl_method_call_respond_success(FlMethodCall* self,
                                                        FlValue* result,
                                                        GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), FALSE);

  g_autoptr(FlMethodResponse) response =
      FL_METHOD_RESPONSE(fl_method_success_response_new(result));
  return fl_method_channel_respond(self->channel, self->response_handle,
                                   response, error);
}

G_MODULE_EXPORT gboolean fl_method_call_respond_error(FlMethodCall* self,
                                                      const gchar* code,
                                                      const gchar* message,
                                                      FlValue* details,
                                                      GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), FALSE);
  g_return_val_if_fail(code != nullptr, FALSE);

  g_autoptr(FlMethodResponse) response =
      FL_METHOD_RESPONSE(fl_method_error_response_new(code, message, details));
  return fl_method_channel_respond(self->channel, self->response_handle,
                                   response, error);
}

G_MODULE_EXPORT gboolean
fl_method_call_respond_not_implemented(FlMethodCall* self, GError** error) {
  g_return_val_if_fail(FL_IS_METHOD_CALL(self), FALSE);

  g_autoptr(FlMethodResponse) response =
      FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
  return fl_method_channel_respond(self->channel, self->response_handle,
                                   response, error);
}
