// 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.

// Included first as it collides with the X11 headers.
#include "gtest/gtest.h"

#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_event_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
#include "flutter/shell/platform/linux/testing/mock_renderer.h"

// Data passed in tests.
typedef struct {
  GMainLoop* loop;
  int count;
} TestData;

// Creates a mock engine that responds to platform messages.
static FlEngine* make_mock_engine() {
  g_autoptr(FlDartProject) project = fl_dart_project_new();
  g_autoptr(FlMockRenderer) renderer = fl_mock_renderer_new();
  g_autoptr(FlEngine) engine = fl_engine_new(project, FL_RENDERER(renderer));
  g_autoptr(GError) engine_error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &engine_error));
  EXPECT_EQ(engine_error, nullptr);

  return static_cast<FlEngine*>(g_object_ref(engine));
}

// Triggers the engine to start listening to the channel.
static void listen_channel(FlBinaryMessenger* messenger, FlValue* args) {
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
      messenger, "test/standard-method", FL_METHOD_CODEC(codec));

  // Trigger the engine to make a method call.
  g_autoptr(FlValue) invoke_args = fl_value_new_list();
  fl_value_append_take(invoke_args, fl_value_new_string("test/standard-event"));
  fl_value_append_take(invoke_args, fl_value_new_string("listen"));
  g_autoptr(FlValue) value =
      args != nullptr ? fl_value_ref(args) : fl_value_new_null();
  fl_value_append(invoke_args, value);
  fl_method_channel_invoke_method(channel, "InvokeMethod", invoke_args, nullptr,
                                  nullptr, nullptr);
}

// Triggers the engine to cancel the subscription to the channel.
static void cancel_channel(FlBinaryMessenger* messenger, FlValue* args) {
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
      messenger, "test/standard-method", FL_METHOD_CODEC(codec));

  // Trigger the engine to make a method call.
  g_autoptr(FlValue) invoke_args = fl_value_new_list();
  fl_value_append_take(invoke_args, fl_value_new_string("test/standard-event"));
  fl_value_append_take(invoke_args, fl_value_new_string("cancel"));
  g_autoptr(FlValue) value =
      args != nullptr ? fl_value_ref(args) : fl_value_new_null();
  fl_value_append(invoke_args, value);
  fl_method_channel_invoke_method(channel, "InvokeMethod", invoke_args, nullptr,
                                  nullptr, nullptr);
}

// Called when when the remote end starts listening on the channel.
static FlMethodErrorResponse* listen_listen_cb(FlEventChannel* channel,
                                               FlValue* args,
                                               gpointer user_data) {
  EXPECT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_NULL);

  g_main_loop_quit(static_cast<GMainLoop*>(user_data));

  return nullptr;
}

// Checks we detect a listen event.
TEST(FlEventChannelTest, Listen) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(channel, listen_listen_cb, nullptr, loop,
                                       nullptr);

  listen_channel(messenger, nullptr);

  // Blocks here until listen_listen_cb called.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}

// Called when when the remote end starts listening on the channel.
static FlMethodErrorResponse* listen_exception_listen_cb(
    FlEventChannel* channel,
    FlValue* args,
    gpointer user_data) {
  return fl_method_error_response_new("LISTEN-ERROR", "LISTEN-ERROR-MESSAGE",
                                      nullptr);
}

// Called when a the test engine notifies us what response we sent in the
// ListenException test.
static void listen_exception_response_cb(
    FlBinaryMessenger* messenger,
    const gchar* channel,
    GBytes* message,
    FlBinaryMessengerResponseHandle* response_handle,
    gpointer user_data) {
  fl_binary_messenger_send_response(messenger, response_handle, nullptr,
                                    nullptr);

  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  g_autoptr(GError) error = nullptr;
  g_autoptr(FlMethodResponse) response =
      fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
  EXPECT_NE(response, nullptr);
  EXPECT_EQ(error, nullptr);

  EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
  EXPECT_STREQ(
      fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)),
      "LISTEN-ERROR");
  EXPECT_STREQ(
      fl_method_error_response_get_message(FL_METHOD_ERROR_RESPONSE(response)),
      "LISTEN-ERROR-MESSAGE");

  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
}

// Checks we can generate a listen exception.
TEST(FlEventChannelTest, ListenException) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(channel, listen_exception_listen_cb,
                                       nullptr, loop, nullptr);

  // Listen for response to the engine.
  fl_binary_messenger_set_message_handler_on_channel(
      messenger, "test/responses", listen_exception_response_cb, loop, nullptr);

  listen_channel(messenger, nullptr);

  // Blocks here until listen_exception_response_cb called.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}

// Called when when the remote end cancels their subscription.
static FlMethodErrorResponse* cancel_cancel_cb(FlEventChannel* channel,
                                               FlValue* args,
                                               gpointer user_data) {
  EXPECT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_NULL);

  g_main_loop_quit(static_cast<GMainLoop*>(user_data));

  return nullptr;
}

// Checks we detect a cancel event.
TEST(FlEventChannelTest, Cancel) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(channel, nullptr, cancel_cancel_cb, loop,
                                       nullptr);

  listen_channel(messenger, nullptr);
  cancel_channel(messenger, nullptr);

  // Blocks here until cancel_cancel_cb called.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}

// Called when when the remote end cancels their subscription.
static FlMethodErrorResponse* cancel_exception_cancel_cb(
    FlEventChannel* channel,
    FlValue* args,
    gpointer user_data) {
  return fl_method_error_response_new("CANCEL-ERROR", "CANCEL-ERROR-MESSAGE",
                                      nullptr);
}

// Called when a the test engine notifies us what response we sent in the
// CancelException test.
static void cancel_exception_response_cb(
    FlBinaryMessenger* messenger,
    const gchar* channel,
    GBytes* message,
    FlBinaryMessengerResponseHandle* response_handle,
    gpointer user_data) {
  TestData* data = static_cast<TestData*>(user_data);

  fl_binary_messenger_send_response(messenger, response_handle, nullptr,
                                    nullptr);

  data->count++;
  if (data->count == 2) {
    g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
    g_autoptr(GError) error = nullptr;
    g_autoptr(FlMethodResponse) response = fl_method_codec_decode_response(
        FL_METHOD_CODEC(codec), message, &error);
    EXPECT_NE(response, nullptr);
    EXPECT_EQ(error, nullptr);

    EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
    EXPECT_STREQ(
        fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)),
        "CANCEL-ERROR");
    EXPECT_STREQ(fl_method_error_response_get_message(
                     FL_METHOD_ERROR_RESPONSE(response)),
                 "CANCEL-ERROR-MESSAGE");

    g_main_loop_quit(data->loop);
  }
}

// Checks we can generate a cancel exception.
TEST(FlEventChannelTest, CancelException) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
  TestData data;
  data.loop = loop;
  data.count = 0;

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(
      channel, nullptr, cancel_exception_cancel_cb, &data, nullptr);

  // Listen for response to the engine.
  fl_binary_messenger_set_message_handler_on_channel(
      messenger, "test/responses", cancel_exception_response_cb, &data,
      nullptr);

  listen_channel(messenger, nullptr);
  cancel_channel(messenger, nullptr);

  // Blocks here until cancel_exception_response_cb called.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}

// Called when when the remote end starts listening on the channel.
static FlMethodErrorResponse* args_listen_cb(FlEventChannel* channel,
                                             FlValue* args,
                                             gpointer user_data) {
  g_autoptr(FlValue) expected_args = fl_value_new_string("LISTEN-ARGS");
  EXPECT_TRUE(fl_value_equal(args, expected_args));

  return nullptr;
}

// Called when when the remote end cancels their subscription.
static FlMethodErrorResponse* args_cancel_cb(FlEventChannel* channel,
                                             FlValue* args,
                                             gpointer user_data) {
  g_autoptr(FlValue) expected_args = fl_value_new_string("CANCEL-ARGS");
  EXPECT_TRUE(fl_value_equal(args, expected_args));

  g_main_loop_quit(static_cast<GMainLoop*>(user_data));

  return nullptr;
}

// Checks args are passed to listen/cancel.
TEST(FlEventChannelTest, Args) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(channel, args_listen_cb, args_cancel_cb,
                                       loop, nullptr);

  g_autoptr(FlValue) listen_args = fl_value_new_string("LISTEN-ARGS");
  listen_channel(messenger, listen_args);
  g_autoptr(FlValue) cancel_args = fl_value_new_string("CANCEL-ARGS");
  cancel_channel(messenger, cancel_args);

  // Blocks here until args_cancel_cb called.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}

// Called when when the remote end starts listening on the channel.
static FlMethodErrorResponse* send_events_listen_cb(FlEventChannel* channel,
                                                    FlValue* args,
                                                    gpointer user_data) {
  // Send some events.
  for (int i = 0; i < 5; i++) {
    g_autoptr(FlValue) event = fl_value_new_int(i);
    g_autoptr(GError) error = nullptr;
    EXPECT_TRUE(fl_event_channel_send(channel, event, nullptr, &error));
    EXPECT_EQ(error, nullptr);
  }

  return nullptr;
}

// Called when a the test engine notifies us what event we sent in the
// Test test.
static void send_events_events_cb(
    FlBinaryMessenger* messenger,
    const gchar* channel,
    GBytes* message,
    FlBinaryMessengerResponseHandle* response_handle,
    gpointer user_data) {
  TestData* data = static_cast<TestData*>(user_data);

  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  g_autoptr(GError) error = nullptr;
  g_autoptr(FlMethodResponse) response =
      fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
  EXPECT_NE(response, nullptr);
  EXPECT_EQ(error, nullptr);

  FlValue* result = fl_method_response_get_result(response, &error);
  EXPECT_NE(result, nullptr);
  EXPECT_EQ(error, nullptr);

  EXPECT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_INT);
  EXPECT_EQ(fl_value_get_int(result), data->count);
  data->count++;

  fl_binary_messenger_send_response(messenger, response_handle, nullptr,
                                    nullptr);

  // Got all the results!
  if (data->count == 5) {
    g_main_loop_quit(data->loop);
  }
}

// Checks can send events.
TEST(FlEventChannelTest, Test) {
  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
  TestData data;
  data.loop = loop;
  data.count = 0;

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  FlEventChannel* channel = fl_event_channel_new(
      messenger, "test/standard-event", FL_METHOD_CODEC(codec));
  fl_event_channel_set_stream_handlers(channel, send_events_listen_cb, nullptr,
                                       &data, nullptr);

  // Listen for events from the engine.
  fl_binary_messenger_set_message_handler_on_channel(
      messenger, "test/events", send_events_events_cb, &data, nullptr);

  listen_channel(messenger, nullptr);
  cancel_channel(messenger, nullptr);

  // Blocks here until send_events_events_cb receives the last event.
  g_main_loop_run(loop);

  // Manually unref because the compiler complains 'channel' is unused.
  g_object_unref(channel);
}
