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

#include <gmodule.h>

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

// See lib/src/services/message_codecs.dart in Flutter source for description of
// encoding.

// Envelope codes.
static constexpr guint8 kEnvelopeTypeSuccess = 0;
static constexpr guint8 kEnvelopeTypeError = 1;

struct _FlStandardMethodCodec {
  FlMethodCodec parent_instance;

  FlStandardMessageCodec* message_codec;
};

enum { kPropMessageCodec = 1, kPropLast };

G_DEFINE_TYPE(FlStandardMethodCodec,
              fl_standard_method_codec,
              fl_method_codec_get_type())

static void fl_standard_method_codec_set_property(GObject* object,
                                                  guint prop_id,
                                                  const GValue* value,
                                                  GParamSpec* pspec) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(object);

  switch (prop_id) {
    case kPropMessageCodec:
      g_set_object(&self->message_codec,
                   FL_STANDARD_MESSAGE_CODEC(g_value_get_object(value)));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
      break;
  }
}

static void fl_standard_method_codec_get_property(GObject* object,
                                                  guint prop_id,
                                                  GValue* value,
                                                  GParamSpec* pspec) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(object);

  switch (prop_id) {
    case kPropMessageCodec:
      g_value_set_object(value, self->message_codec);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
      break;
  }
}

static void fl_standard_method_codec_dispose(GObject* object) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(object);

  g_clear_object(&self->message_codec);

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

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

  g_autoptr(GByteArray) buffer = g_byte_array_new();
  g_autoptr(FlValue) name_value = fl_value_new_string(name);
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer,
                                             name_value, error)) {
    return nullptr;
  }
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer, args,
                                             error)) {
    return nullptr;
  }

  return g_byte_array_free_to_bytes(
      static_cast<GByteArray*>(g_steal_pointer(&buffer)));
}

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

  size_t offset = 0;
  g_autoptr(FlValue) name_value = fl_standard_message_codec_read_value(
      self->message_codec, message, &offset, error);
  if (name_value == nullptr) {
    return FALSE;
  }
  if (fl_value_get_type(name_value) != FL_VALUE_TYPE_STRING) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Method call name wrong type");
    return FALSE;
  }

  g_autoptr(FlValue) args_value = fl_standard_message_codec_read_value(
      self->message_codec, message, &offset, error);
  if (args_value == nullptr) {
    return FALSE;
  }

  if (offset != g_bytes_get_size(message)) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Unexpected extra data");
    return FALSE;
  }

  *name = g_strdup(fl_value_get_string(name_value));
  *args = fl_value_ref(args_value);

  return TRUE;
}

// Implements FlMethodCodec::encode_success_envelope.
static GBytes* fl_standard_method_codec_encode_success_envelope(
    FlMethodCodec* codec,
    FlValue* result,
    GError** error) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);

  g_autoptr(GByteArray) buffer = g_byte_array_new();
  guint8 type = kEnvelopeTypeSuccess;
  g_byte_array_append(buffer, &type, 1);
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer,
                                             result, error)) {
    return nullptr;
  }

  return g_byte_array_free_to_bytes(
      static_cast<GByteArray*>(g_steal_pointer(&buffer)));
}

// Implements FlMethodCodec::encode_error_envelope.
static GBytes* fl_standard_method_codec_encode_error_envelope(
    FlMethodCodec* codec,
    const gchar* code,
    const gchar* message,
    FlValue* details,
    GError** error) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);

  g_autoptr(GByteArray) buffer = g_byte_array_new();
  guint8 type = kEnvelopeTypeError;
  g_byte_array_append(buffer, &type, 1);
  g_autoptr(FlValue) code_value = fl_value_new_string(code);
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer,
                                             code_value, error)) {
    return nullptr;
  }
  g_autoptr(FlValue) message_value =
      message != nullptr ? fl_value_new_string(message) : nullptr;
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer,
                                             message_value, error)) {
    return nullptr;
  }
  if (!fl_standard_message_codec_write_value(self->message_codec, buffer,
                                             details, error)) {
    return nullptr;
  }

  return g_byte_array_free_to_bytes(
      static_cast<GByteArray*>(g_steal_pointer(&buffer)));
}

// Implements FlMethodCodec::encode_decode_response.
static FlMethodResponse* fl_standard_method_codec_decode_response(
    FlMethodCodec* codec,
    GBytes* message,
    GError** error) {
  FlStandardMethodCodec* self = FL_STANDARD_METHOD_CODEC(codec);

  if (g_bytes_get_size(message) == 0) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR,
                FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA, "Empty response");
    return nullptr;
  }

  // First byte is response type.
  const guint8* data =
      static_cast<const guint8*>(g_bytes_get_data(message, nullptr));
  guint8 type = data[0];
  size_t offset = 1;

  g_autoptr(FlMethodResponse) response = nullptr;
  if (type == kEnvelopeTypeError) {
    g_autoptr(FlValue) code = fl_standard_message_codec_read_value(
        self->message_codec, message, &offset, error);
    if (code == nullptr) {
      return nullptr;
    }
    if (fl_value_get_type(code) != FL_VALUE_TYPE_STRING) {
      g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                  "Error code wrong type");
      return nullptr;
    }

    g_autoptr(FlValue) error_message = fl_standard_message_codec_read_value(
        self->message_codec, message, &offset, error);
    if (error_message == nullptr) {
      return nullptr;
    }
    if (fl_value_get_type(error_message) != FL_VALUE_TYPE_STRING &&
        fl_value_get_type(error_message) != FL_VALUE_TYPE_NULL) {
      g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                  "Error message wrong type");
      return nullptr;
    }

    g_autoptr(FlValue) details = fl_standard_message_codec_read_value(
        self->message_codec, message, &offset, error);
    if (details == nullptr) {
      return nullptr;
    }

    response = FL_METHOD_RESPONSE(fl_method_error_response_new(
        fl_value_get_string(code),
        fl_value_get_type(error_message) == FL_VALUE_TYPE_STRING
            ? fl_value_get_string(error_message)
            : nullptr,
        fl_value_get_type(details) != FL_VALUE_TYPE_NULL ? details : nullptr));
  } else if (type == kEnvelopeTypeSuccess) {
    g_autoptr(FlValue) result = fl_standard_message_codec_read_value(
        self->message_codec, message, &offset, error);

    if (result == nullptr) {
      return nullptr;
    }

    response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
  } else {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Unknown envelope type %02x", type);
    return nullptr;
  }

  if (offset != g_bytes_get_size(message)) {
    g_set_error(error, FL_MESSAGE_CODEC_ERROR, FL_MESSAGE_CODEC_ERROR_FAILED,
                "Unexpected extra data");
    return nullptr;
  }

  return FL_METHOD_RESPONSE(g_object_ref(response));
}

static void fl_standard_method_codec_class_init(
    FlStandardMethodCodecClass* klass) {
  G_OBJECT_CLASS(klass)->set_property = fl_standard_method_codec_set_property;
  G_OBJECT_CLASS(klass)->get_property = fl_standard_method_codec_get_property;
  G_OBJECT_CLASS(klass)->dispose = fl_standard_method_codec_dispose;

  FL_METHOD_CODEC_CLASS(klass)->encode_method_call =
      fl_standard_method_codec_encode_method_call;
  FL_METHOD_CODEC_CLASS(klass)->decode_method_call =
      fl_standard_method_codec_decode_method_call;
  FL_METHOD_CODEC_CLASS(klass)->encode_success_envelope =
      fl_standard_method_codec_encode_success_envelope;
  FL_METHOD_CODEC_CLASS(klass)->encode_error_envelope =
      fl_standard_method_codec_encode_error_envelope;
  FL_METHOD_CODEC_CLASS(klass)->decode_response =
      fl_standard_method_codec_decode_response;

  g_object_class_install_property(
      G_OBJECT_CLASS(klass), kPropMessageCodec,
      g_param_spec_object(
          "message-codec", "message-codec", "Message codec to use",
          fl_message_codec_get_type(),
          static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                                   G_PARAM_STATIC_STRINGS)));
}

static void fl_standard_method_codec_init(FlStandardMethodCodec* self) {}

G_MODULE_EXPORT FlStandardMethodCodec* fl_standard_method_codec_new() {
  g_autoptr(FlStandardMessageCodec) message_codec =
      fl_standard_message_codec_new();
  return fl_standard_method_codec_new_with_message_codec(message_codec);
}

G_MODULE_EXPORT FlStandardMethodCodec*
fl_standard_method_codec_new_with_message_codec(
    FlStandardMessageCodec* message_codec) {
  return FL_STANDARD_METHOD_CODEC(
      g_object_new(fl_standard_method_codec_get_type(), "message-codec",
                   message_codec, nullptr));
}
