// 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/common/cpp/json_method_codec.h"

#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_result_functions.h"
#include "gtest/gtest.h"

namespace flutter {

namespace {

// Returns true if the given method calls have the same method name, and their
// arguments have equivalent values.
bool MethodCallsAreEqual(const MethodCall<rapidjson::Document>& a,
                         const MethodCall<rapidjson::Document>& b) {
  if (a.method_name() != b.method_name()) {
    return false;
  }
  // Treat nullptr and Null as equivalent.
  if ((!a.arguments() || a.arguments()->IsNull()) &&
      (!b.arguments() || b.arguments()->IsNull())) {
    return true;
  }
  return *a.arguments() == *b.arguments();
}

}  // namespace

TEST(JsonMethodCodec, HandlesMethodCallsWithNullArguments) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();
  MethodCall<rapidjson::Document> call("hello", nullptr);
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_TRUE(encoded);
  std::unique_ptr<MethodCall<rapidjson::Document>> decoded =
      codec.DecodeMethodCall(*encoded);
  ASSERT_TRUE(decoded);
  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
}

TEST(JsonMethodCodec, HandlesMethodCallsWithArgument) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();

  auto arguments = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
  auto& allocator = arguments->GetAllocator();
  arguments->PushBack(42, allocator);
  arguments->PushBack("world", allocator);
  MethodCall<rapidjson::Document> call("hello", std::move(arguments));
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_TRUE(encoded);
  std::unique_ptr<MethodCall<rapidjson::Document>> decoded =
      codec.DecodeMethodCall(*encoded);
  ASSERT_TRUE(decoded);
  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
}

TEST(JsonMethodCodec, HandlesSuccessEnvelopesWithNullResult) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();
  auto encoded = codec.EncodeSuccessEnvelope();
  ASSERT_TRUE(encoded);
  std::vector<uint8_t> bytes = {'[', 'n', 'u', 'l', 'l', ']'};
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<rapidjson::Document> result_handler(
      [&decoded_successfully](const rapidjson::Document* result) {
        decoded_successfully = true;
        EXPECT_EQ(result, nullptr);
      },
      nullptr, nullptr);
  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
                                         &result_handler);
  EXPECT_TRUE(decoded_successfully);
}

TEST(JsonMethodCodec, HandlesSuccessEnvelopesWithResult) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();
  rapidjson::Document result;
  result.SetInt(42);
  auto encoded = codec.EncodeSuccessEnvelope(&result);
  ASSERT_TRUE(encoded);
  std::vector<uint8_t> bytes = {'[', '4', '2', ']'};
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<rapidjson::Document> result_handler(
      [&decoded_successfully](const rapidjson::Document* result) {
        decoded_successfully = true;
        EXPECT_EQ(result->GetInt(), 42);
      },
      nullptr, nullptr);
  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
                                         &result_handler);
  EXPECT_TRUE(decoded_successfully);
}

TEST(JsonMethodCodec, HandlesErrorEnvelopesWithNulls) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();
  auto encoded = codec.EncodeErrorEnvelope("errorCode");
  ASSERT_TRUE(encoded);
  std::vector<uint8_t> bytes = {
      '[', '"', 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e',
      '"', ',', '"', '"', ',', 'n', 'u', 'l', 'l', ']',
  };
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<rapidjson::Document> result_handler(
      nullptr,
      [&decoded_successfully](const std::string& code,
                              const std::string& message,
                              const rapidjson::Document* details) {
        decoded_successfully = true;
        EXPECT_EQ(code, "errorCode");
        EXPECT_EQ(message, "");
        EXPECT_EQ(details, nullptr);
      },
      nullptr);
  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
                                         &result_handler);
  EXPECT_TRUE(decoded_successfully);
}

TEST(JsonMethodCodec, HandlesErrorEnvelopesWithDetails) {
  const JsonMethodCodec& codec = JsonMethodCodec::GetInstance();
  rapidjson::Document details(rapidjson::kArrayType);
  auto& allocator = details.GetAllocator();
  details.PushBack("a", allocator);
  details.PushBack(42, allocator);
  auto encoded =
      codec.EncodeErrorEnvelope("errorCode", "something failed", &details);
  ASSERT_NE(encoded.get(), nullptr);
  std::vector<uint8_t> bytes = {
      '[', '"', 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e', '"', ',', '"',
      's', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', ' ', 'f', 'a', 'i', 'l',
      'e', 'd', '"', ',', '[', '"', 'a', '"', ',', '4', '2', ']', ']',
  };
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<rapidjson::Document> result_handler(
      nullptr,
      [&decoded_successfully](const std::string& code,
                              const std::string& message,
                              const rapidjson::Document* details) {
        decoded_successfully = true;
        EXPECT_EQ(code, "errorCode");
        EXPECT_EQ(message, "something failed");
        EXPECT_TRUE(details->IsArray());
        EXPECT_EQ(std::string((*details)[0].GetString()), "a");
        EXPECT_EQ((*details)[1].GetInt(), 42);
      },
      nullptr);
  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
                                         &result_handler);
  EXPECT_TRUE(decoded_successfully);
}

}  // namespace flutter
