// 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<EncodableValue>& a,
                         const MethodCall<EncodableValue>& 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<EncodableValue> call("hello", nullptr);
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_NE(encoded.get(), nullptr);
  std::unique_ptr<MethodCall<EncodableValue>> decoded =
      codec.DecodeMethodCall(*encoded);
  ASSERT_NE(decoded.get(), nullptr);
  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
}

TEST(StandardMethodCodec, HandlesMethodCallsWithArgument) {
  const StandardMethodCodec& codec = StandardMethodCodec::GetInstance();
  MethodCall<EncodableValue> 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<EncodableValue>> 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<EncodableValue> 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<EncodableValue> 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<EncodableValue> 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<EncodableValue> 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<EncodableValue> call(
      "hello", std::make_unique<EncodableValue>(CustomEncodableValue(point)));
  auto encoded = codec.EncodeMethodCall(call);
  ASSERT_NE(encoded.get(), nullptr);
  std::unique_ptr<MethodCall<EncodableValue>> 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
