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

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

#include <gmodule.h>

static constexpr char kMethodKey[] = "method";
static constexpr char kArgsKey[] = "args";

struct _FlJsonMethodCodec {
  FlMethodCodec parent_instance;

  FlJsonMessageCodec* codec;
};

G_DEFINE_TYPE(FlJsonMethodCodec,
              fl_json_method_codec,
              fl_method_codec_get_type())

static void fl_json_method_codec_dispose(GObject* object) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(object);

  g_clear_object(&self->codec);

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

// Implements FlMethodCodec::encode_method_call.
static GBytes* fl_json_method_codec_encode_method_call(FlMethodCodec* codec,
                                                       const gchar* name,
                                                       FlValue* args,
                                                       GError** error) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(codec);

  g_autoptr(FlValue) message = fl_value_new_map();
  fl_value_set_take(message, fl_value_new_string(kMethodKey),
                    fl_value_new_string(name));
  fl_value_set_take(message, fl_value_new_string(kArgsKey),
                    args != nullptr ? fl_value_ref(args) : fl_value_new_null());

  return fl_message_codec_encode_message(FL_MESSAGE_CODEC(self->codec), message,
                                         error);
}

// Implements FlMethodCodec::decode_method_call.
static gboolean fl_json_method_codec_decode_method_call(FlMethodCodec* codec,
                                                        GBytes* message,
                                                        gchar** name,
                                                        FlValue** args,
                                                        GError** error) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(codec);

  g_autoptr(FlValue) value = fl_message_codec_decode_message(
      FL_MESSAGE_CODEC(self->codec), message, error);
  if (value == nullptr)
    return FALSE;

  if (fl_value_get_type(value) != FL_VALUE_TYPE_MAP) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Expected JSON map in method resonse, got %d instead",
                fl_value_get_type(value));
    return FALSE;
  }

  FlValue* method_value = fl_value_lookup_string(value, kMethodKey);
  if (method_value == nullptr) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Missing JSON method field in method resonse");
    return FALSE;
  }
  if (fl_value_get_type(method_value) != FL_VALUE_TYPE_STRING) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Expected JSON string for method name, got %d instead",
                fl_value_get_type(method_value));
    return FALSE;
  }
  FlValue* args_value = fl_value_lookup_string(value, kArgsKey);

  *name = g_strdup(fl_value_get_string(method_value));
  *args = args_value != nullptr ? fl_value_ref(args_value) : nullptr;

  return TRUE;
}

// Implements FlMethodCodec::encode_success_envelope.
static GBytes* fl_json_method_codec_encode_success_envelope(
    FlMethodCodec* codec,
    FlValue* result,
    GError** error) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(codec);

  g_autoptr(FlValue) message = fl_value_new_list();
  fl_value_append_take(
      message, result != nullptr ? fl_value_ref(result) : fl_value_new_null());

  return fl_message_codec_encode_message(FL_MESSAGE_CODEC(self->codec), message,
                                         error);
}

// Implements FlMethodCodec::encode_error_envelope.
static GBytes* fl_json_method_codec_encode_error_envelope(
    FlMethodCodec* codec,
    const gchar* code,
    const gchar* error_message,
    FlValue* details,
    GError** error) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(codec);

  g_autoptr(FlValue) message = fl_value_new_list();
  fl_value_append_take(message, fl_value_new_string(code));
  fl_value_append_take(message, error_message != nullptr
                                    ? fl_value_new_string(error_message)
                                    : fl_value_new_null());
  fl_value_append_take(message, details != nullptr ? fl_value_ref(details)
                                                   : fl_value_new_null());

  return fl_message_codec_encode_message(FL_MESSAGE_CODEC(self->codec), message,
                                         error);
}

// Implements FlMethodCodec::decode_response.
static FlMethodResponse* fl_json_method_codec_decode_response(
    FlMethodCodec* codec,
    GBytes* message,
    GError** error) {
  FlJsonMethodCodec* self = FL_JSON_METHOD_CODEC(codec);

  g_autoptr(FlValue) value = fl_message_codec_decode_message(
      FL_MESSAGE_CODEC(self->codec), message, error);
  if (value == nullptr)
    return nullptr;

  if (fl_value_get_type(value) != FL_VALUE_TYPE_LIST) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Expected JSON list in method resonse, got %d instead",
                fl_value_get_type(value));
    return nullptr;
  }

  size_t length = fl_value_get_length(value);
  if (length == 1) {
    return FL_METHOD_RESPONSE(
        fl_method_success_response_new(fl_value_get_list_value(value, 0)));
  } else if (length == 3) {
    FlValue* code_value = fl_value_get_list_value(value, 0);
    if (fl_value_get_type(code_value) != FL_VALUE_TYPE_STRING) {
      g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                  "Error code wrong type");
      return nullptr;
    }
    const gchar* code = fl_value_get_string(code_value);

    FlValue* message_value = fl_value_get_list_value(value, 1);
    if (fl_value_get_type(message_value) != FL_VALUE_TYPE_STRING &&
        fl_value_get_type(message_value) != FL_VALUE_TYPE_NULL) {
      g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                  "Error message wrong type");
      return nullptr;
    }
    const gchar* message =
        fl_value_get_type(message_value) == FL_VALUE_TYPE_STRING
            ? fl_value_get_string(message_value)
            : nullptr;

    FlValue* args = fl_value_get_list_value(value, 2);
    if (fl_value_get_type(args) == FL_VALUE_TYPE_NULL)
      args = nullptr;

    return FL_METHOD_RESPONSE(
        fl_method_error_response_new(code, message, args));
  } else {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Got response envelope of length %zi, expected 1 (success) or "
                "3 (error)",
                length);
    return nullptr;
  }
}

static void fl_json_method_codec_class_init(FlJsonMethodCodecClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_json_method_codec_dispose;
  FL_METHOD_CODEC_CLASS(klass)->encode_method_call =
      fl_json_method_codec_encode_method_call;
  FL_METHOD_CODEC_CLASS(klass)->decode_method_call =
      fl_json_method_codec_decode_method_call;
  FL_METHOD_CODEC_CLASS(klass)->encode_success_envelope =
      fl_json_method_codec_encode_success_envelope;
  FL_METHOD_CODEC_CLASS(klass)->encode_error_envelope =
      fl_json_method_codec_encode_error_envelope;
  FL_METHOD_CODEC_CLASS(klass)->decode_response =
      fl_json_method_codec_decode_response;
}

static void fl_json_method_codec_init(FlJsonMethodCodec* self) {
  self->codec = fl_json_message_codec_new();
}

G_MODULE_EXPORT FlJsonMethodCodec* fl_json_method_codec_new() {
  return static_cast<FlJsonMethodCodec*>(
      g_object_new(fl_json_method_codec_get_type(), nullptr));
}
