// 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/client_wrapper/include/flutter/method_result_functions.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/standard_method_codec.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/testing/test_codec_extensions.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<>& a, const MethodCall<>& 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;
  }
  // If only one is nullptr, fail early rather than throw below.
  if (!a.arguments() || !b.arguments()) {
    return false;
  }
  return *a.arguments() == *b.arguments();
}

}  // namespace

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

TEST(StandardMethodCodec, HandlesMethodCallsWithArgument) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  MethodCall<> call("hello", std::make_unique<EncodableValue>(EncodableList{
                                 EncodableValue(42),
                                 EncodableValue("world"),
                             }));
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_NE(encoded.get(), nullptr);
  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
  ASSERT_NE(decoded.get(), nullptr);
  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
}

TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithNullResult) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  auto encoded = codec.EncodeSuccessEnvelope();
  ASSERT_NE(encoded.get(), nullptr);
  std::vector<uint8_t> bytes = {0x00, 0x00};
  EXPECT_EQ(*encoded, bytes);

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

TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithResult) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  EncodableValue result(42);
  auto encoded = codec.EncodeSuccessEnvelope(&result);
  ASSERT_NE(encoded.get(), nullptr);
  std::vector<uint8_t> bytes = {0x00, 0x03, 0x2a, 0x00, 0x00, 0x00};
  EXPECT_EQ(*encoded, bytes);

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

TEST(StandardMethodCodec, HandlesErrorEnvelopesWithNulls) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  auto encoded = codec.EncodeErrorEnvelope("errorCode");
  ASSERT_NE(encoded.get(), nullptr);
  std::vector<uint8_t> bytes = {0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f,
                                0x72, 0x43, 0x6f, 0x64, 0x65, 0x00, 0x00};
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<> result_handler(
      nullptr,
      [&decoded_successfully](const std::string& code,
                              const std::string& message,
                              const EncodableValue* 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(StandardMethodCodec, HandlesErrorEnvelopesWithDetails) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  EncodableValue details(EncodableList{
      EncodableValue("a"),
      EncodableValue(42),
  });
  auto encoded =
      codec.EncodeErrorEnvelope("errorCode", "something failed", &details);
  ASSERT_NE(encoded.get(), nullptr);
  std::vector<uint8_t> bytes = {
      0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f,
      0x64, 0x65, 0x07, 0x10, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
      0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
      0x0c, 0x02, 0x07, 0x01, 0x61, 0x03, 0x2a, 0x00, 0x00, 0x00,
  };
  EXPECT_EQ(*encoded, bytes);

  bool decoded_successfully = false;
  MethodResultFunctions<> result_handler(
      nullptr,
      [&decoded_successfully](const std::string& code,
                              const std::string& message,
                              const EncodableValue* details) {
        decoded_successfully = true;
        EXPECT_EQ(code, "errorCode");
        EXPECT_EQ(message, "something failed");
        const auto* details_list = std::get_if<EncodableList>(details);
        ASSERT_NE(details_list, nullptr);
        EXPECT_EQ(std::get<std::string>((*details_list)[0]), "a");
        EXPECT_EQ(std::get<int32_t>((*details_list)[1]), 42);
      },
      nullptr);
  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
                                         &result_handler);
  EXPECT_TRUE(decoded_successfully);
}

TEST(StandardMethodCodec, HandlesCustomTypeArguments) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance(
      &PointExtensionSerializer::GetInstance());
  Point point(7, 9);
  MethodCall<> call(
      "hello", std::make_unique<EncodableValue>(CustomEncodableValue(point)));
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_NE(encoded.get(), nullptr);
  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
  ASSERT_NE(decoded.get(), nullptr);

  const Point& decoded_point = std::any_cast<Point>(
      std::get<CustomEncodableValue>(*decoded->arguments()));
  EXPECT_EQ(point, decoded_point);
};

}  // namespace flutter
