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