// 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/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_method_codec_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_response.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
#include "gtest/gtest.h"

#include <string.h>

struct _FlutterEngine {
  bool running;
  FlutterPlatformMessageCallback platform_message_callback;
  FlutterTaskRunnerPostTaskCallback platform_post_task_callback;
  void* user_data;

  _FlutterEngine(FlutterPlatformMessageCallback platform_message_callback,
                 FlutterTaskRunnerPostTaskCallback platform_post_task_callback,
                 void* user_data)
      : running(false),
        platform_message_callback(platform_message_callback),
        platform_post_task_callback(platform_post_task_callback),
        user_data(user_data) {}
};

struct _FlutterPlatformMessageResponseHandle {
  FlutterDataCallback data_callback;
  void* user_data;
  std::string channel;
  bool released;

  // Constructor for a response handle generated by the engine.
  _FlutterPlatformMessageResponseHandle(std::string channel)
      : data_callback(nullptr),
        user_data(nullptr),
        channel(channel),
        released(false) {}

  // Constructor for a response handle generated by the shell.
  _FlutterPlatformMessageResponseHandle(FlutterDataCallback data_callback,
                                        void* user_data)
      : data_callback(data_callback), user_data(user_data), released(false) {}
};

struct _FlutterTaskRunner {
  uint64_t task;
  std::string channel;
  const FlutterPlatformMessageResponseHandle* response_handle;
  uint8_t* message;
  size_t message_size;

  _FlutterTaskRunner(
      uint64_t task,
      const std::string& channel,
      const FlutterPlatformMessageResponseHandle* response_handle,
      const uint8_t* message,
      size_t message_size)
      : task(task),
        channel(channel),
        response_handle(response_handle),
        message_size(message_size) {
    this->message = static_cast<uint8_t*>(malloc(message_size));
    memcpy(this->message, message, message_size);
  }
  ~_FlutterTaskRunner() {
    if (response_handle != nullptr) {
      EXPECT_TRUE(response_handle->released);
      delete response_handle;
    }
    free(message);
  }
};

// Send a response from the engine.
static void send_response(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    const std::string& channel,
    const FlutterPlatformMessageResponseHandle* response_handle,
    const uint8_t* message,
    size_t message_size) {
  if (response_handle == nullptr)
    return;

  FlutterTask task;
  task.runner = new _FlutterTaskRunner(1234, channel, response_handle, message,
                                       message_size);
  task.task = task.runner->task;
  engine->platform_post_task_callback(task, 0, engine->user_data);
}

// Send a message from the engine.
static void send_message(FLUTTER_API_SYMBOL(FlutterEngine) engine,
                         const std::string& channel,
                         const uint8_t* message,
                         size_t message_size) {
  FlutterTask task;
  task.runner =
      new _FlutterTaskRunner(1234, channel, nullptr, message, message_size);
  task.task = task.runner->task;
  engine->platform_post_task_callback(task, 0, engine->user_data);
}

static void invoke_method(FLUTTER_API_SYMBOL(FlutterEngine) engine,
                          const std::string& channel,
                          const gchar* name,
                          FlValue* args) {
  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
  g_autoptr(GError) error = nullptr;
  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
      FL_METHOD_CODEC(codec), name, args, &error);
  EXPECT_NE(message, nullptr);
  EXPECT_EQ(error, nullptr);

  FlutterTask task;
  task.runner = new _FlutterTaskRunner(
      1234, channel, nullptr,
      static_cast<const uint8_t*>(g_bytes_get_data(message, nullptr)),
      g_bytes_get_size(message));
  task.task = task.runner->task;
  engine->platform_post_task_callback(task, 0, engine->user_data);
}

FlutterEngineResult FlutterEngineRun(size_t version,
                                     const FlutterRendererConfig* config,
                                     const FlutterProjectArgs* args,
                                     void* user_data,
                                     FLUTTER_API_SYMBOL(FlutterEngine) *
                                         engine_out) {
  EXPECT_NE(config, nullptr);
  EXPECT_NE(args, nullptr);
  EXPECT_NE(user_data, nullptr);
  EXPECT_NE(engine_out, nullptr);

  FlutterEngineResult result =
      FlutterEngineInitialize(version, config, args, user_data, engine_out);
  if (result != kSuccess)
    return result;
  return FlutterEngineRunInitialized(*engine_out);
}

FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine)
                                              engine) {
  delete engine;
  return kSuccess;
}

FlutterEngineResult FlutterEngineInitialize(size_t version,
                                            const FlutterRendererConfig* config,
                                            const FlutterProjectArgs* args,
                                            void* user_data,
                                            FLUTTER_API_SYMBOL(FlutterEngine) *
                                                engine_out) {
  EXPECT_NE(config, nullptr);

  EXPECT_NE(args, nullptr);
  EXPECT_NE(args->platform_message_callback, nullptr);
  EXPECT_NE(args->custom_task_runners, nullptr);
  EXPECT_NE(args->custom_task_runners->platform_task_runner, nullptr);
  EXPECT_NE(args->custom_task_runners->platform_task_runner->post_task_callback,
            nullptr);

  EXPECT_NE(user_data, nullptr);

  EXPECT_EQ(config->type, kOpenGL);

  *engine_out = new _FlutterEngine(
      args->platform_message_callback,
      args->custom_task_runners->platform_task_runner->post_task_callback,
      user_data);
  return kSuccess;
}

FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine)
                                                  engine) {
  return kSuccess;
}

FlutterEngineResult FlutterEngineRunInitialized(
    FLUTTER_API_SYMBOL(FlutterEngine) engine) {
  engine->running = true;
  return kSuccess;
}

FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    const FlutterWindowMetricsEvent* event) {
  EXPECT_TRUE(engine->running);
  return kSuccess;
}

FlutterEngineResult FlutterEngineSendPointerEvent(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    const FlutterPointerEvent* events,
    size_t events_count) {
  return kSuccess;
}

FLUTTER_EXPORT
FlutterEngineResult FlutterEngineSendPlatformMessage(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    const FlutterPlatformMessage* message) {
  EXPECT_TRUE(engine->running);

  if (strcmp(message->channel, "test/echo") == 0) {
    // Responds with the same message received.
    send_response(engine, message->channel, message->response_handle,
                  message->message, message->message_size);
  } else if (strcmp(message->channel, "test/send-message") == 0) {
    // Triggers the engine to send a message.
    send_response(engine, message->channel, message->response_handle, nullptr,
                  0);
    send_message(engine, "test/messages", message->message,
                 message->message_size);
  } else if (strcmp(message->channel, "test/standard-method") == 0) {
    g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
    g_autoptr(GBytes) m = g_bytes_new(message->message, message->message_size);
    g_autofree gchar* name = nullptr;
    g_autoptr(FlValue) args = nullptr;
    g_autoptr(GError) error = nullptr;
    EXPECT_TRUE(fl_method_codec_decode_method_call(FL_METHOD_CODEC(codec), m,
                                                   &name, &args, &error));
    EXPECT_EQ(error, nullptr);

    g_autoptr(GBytes) response = nullptr;
    if (strcmp(name, "Echo") == 0) {
      // Returns args as a success result.
      response = fl_method_codec_encode_success_envelope(FL_METHOD_CODEC(codec),
                                                         args, &error);
      EXPECT_EQ(error, nullptr);
    } else if (strcmp(name, "Error") == 0) {
      // Returns an error result.
      const gchar* code = nullptr;
      const gchar* message = nullptr;
      FlValue* details = nullptr;
      if (fl_value_get_length(args) >= 2) {
        FlValue* code_value = fl_value_get_list_value(args, 0);
        EXPECT_EQ(fl_value_get_type(code_value), FL_VALUE_TYPE_STRING);
        code = fl_value_get_string(code_value);
        FlValue* message_value = fl_value_get_list_value(args, 1);
        message = fl_value_get_type(message_value) == FL_VALUE_TYPE_STRING
                      ? fl_value_get_string(message_value)
                      : nullptr;
      }
      if (fl_value_get_length(args) >= 3)
        details = fl_value_get_list_value(args, 2);
      response = fl_method_codec_encode_error_envelope(
          FL_METHOD_CODEC(codec), code, message, details, &error);
      EXPECT_EQ(error, nullptr);
    } else if (strcmp(name, "InvokeMethod") == 0) {
      // Gets the engine to call the shell.
      if (fl_value_get_length(args) == 3) {
        FlValue* channel_value = fl_value_get_list_value(args, 0);
        EXPECT_EQ(fl_value_get_type(channel_value), FL_VALUE_TYPE_STRING);
        const gchar* channel = fl_value_get_string(channel_value);
        FlValue* name_value = fl_value_get_list_value(args, 1);
        EXPECT_EQ(fl_value_get_type(name_value), FL_VALUE_TYPE_STRING);
        const gchar* name = fl_value_get_string(name_value);
        FlValue* method_args = fl_value_get_list_value(args, 2);
        invoke_method(engine, channel, name, method_args);
      }
      response = fl_method_codec_encode_success_envelope(FL_METHOD_CODEC(codec),
                                                         nullptr, &error);
      EXPECT_EQ(error, nullptr);
    } else {
      // Returns "not implemented".
      response = g_bytes_new(nullptr, 0);
    }

    send_response(
        engine, message->channel, message->response_handle,
        static_cast<const uint8_t*>(g_bytes_get_data(response, nullptr)),
        g_bytes_get_size(response));
  } else if (strcmp(message->channel, "test/nullptr-response") == 0) {
    // Sends a null response.
    send_response(engine, message->channel, message->response_handle, nullptr,
                  0);
  } else if (strcmp(message->channel, "test/failure") == 0) {
    // Generates an internal error.
    return kInternalInconsistency;
  }

  return kSuccess;
}

FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    FlutterDataCallback data_callback,
    void* user_data,
    FlutterPlatformMessageResponseHandle** response_out) {
  EXPECT_TRUE(engine->running);
  EXPECT_NE(data_callback, nullptr);
  EXPECT_NE(user_data, nullptr);

  _FlutterPlatformMessageResponseHandle* handle =
      new _FlutterPlatformMessageResponseHandle(data_callback, user_data);

  *response_out = handle;
  return kSuccess;
}

FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    FlutterPlatformMessageResponseHandle* response) {
  EXPECT_NE(engine, nullptr);
  EXPECT_NE(response, nullptr);

  EXPECT_TRUE(engine->running);

  EXPECT_FALSE(response->released);
  response->released = true;

  return kSuccess;
}

FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
    FLUTTER_API_SYMBOL(FlutterEngine) engine,
    const FlutterPlatformMessageResponseHandle* handle,
    const uint8_t* data,
    size_t data_length) {
  EXPECT_NE(engine, nullptr);
  EXPECT_NE(handle, nullptr);

  EXPECT_TRUE(engine->running);

  // Send a message so the shell can check the responses received.
  if (handle->channel != "test/responses")
    send_message(engine, "test/responses", data, data_length);

  EXPECT_FALSE(handle->released);

  delete handle;

  return kSuccess;
}

FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine)
                                             engine,
                                         const FlutterTask* task) {
  EXPECT_NE(engine, nullptr);
  EXPECT_NE(task, nullptr);
  EXPECT_NE(task->runner, nullptr);

  FlutterTaskRunner runner = task->runner;
  EXPECT_NE(runner, nullptr);
  const FlutterPlatformMessageResponseHandle* response_handle =
      runner->response_handle;
  if (response_handle != nullptr) {
    EXPECT_NE(response_handle->data_callback, nullptr);
    response_handle->data_callback(runner->message, runner->message_size,
                                   response_handle->user_data);
  } else {
    _FlutterPlatformMessageResponseHandle* handle =
        new _FlutterPlatformMessageResponseHandle(runner->channel);

    FlutterPlatformMessage message;
    message.struct_size = sizeof(FlutterPlatformMessage);
    message.channel = runner->channel.c_str();
    message.message = runner->message;
    message.message_size = runner->message_size;
    message.response_handle = handle;
    engine->platform_message_callback(&message, engine->user_data);
  }

  delete runner;

  return kSuccess;
}
