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