// Copyright 2018 The Fuchsia 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 <list>

#include <fidl/test/misc/cpp/fidl.h>
#include <gtest/gtest.h>

#include "lib/fidl/cpp/clone.h"
#include "lib/fidl/cpp/optional.h"

namespace fidl {
namespace test {
namespace misc {
namespace {

// Takes a collection of distinct elements, and checks that the comparison
// operators are correct.
template <typename A>
::testing::AssertionResult CheckComparison(const std::vector<A>& v) {
  for (size_t i = 0; i < v.size(); ++i) {
    EXPECT_TRUE(fidl::Equals(v[i], fidl::Clone(v[i])));
    for (size_t j = 0; j < v.size(); ++j) {
      if ((i == j) != fidl::Equals(v[i], v[j])) {
        return ::testing::AssertionFailure() << "fidl::Equals incorrect for " << i << " and " << j;
      }
      if ((i != j) != !fidl::Equals(v[i], v[j])) {
        return ::testing::AssertionFailure() << "fidl::Equals incorrect for " << i << " and " << j;
      }
    }
  }
  return ::testing::AssertionSuccess();
}

TEST(FidlTest, BitsComparison) {
  std::vector<Uint32Bits> bits;
  bits.push_back(Uint32Bits::ONE);
  bits.push_back(Uint32Bits::TWO);
  EXPECT_TRUE(CheckComparison(bits));
}

TEST(FidlTest, SimpleStructComparison) {
  // Create a vector of structs.
  std::vector<Int64Struct> structs;
  for (int32_t i = 1; i < 3; ++i) {
    structs.push_back(Int64Struct{i});
  }
  EXPECT_TRUE(CheckComparison(structs));
}

TEST(FidlTest, SimpleTableComparison) {
  // Create a vector of tables.
  std::vector<SimpleTable> tables;
  for (int32_t i = 1; i < 3; ++i) {
    SimpleTable t;
    t.set_x(i);
    t.set_y(-i);
    tables.push_back(std::move(t));
  }
  EXPECT_TRUE(CheckComparison(tables));
}

TEST(FidlTest, StructWithNullComparison) {
  // Create a vector of structs.
  std::vector<HasOptionalFieldStruct> structs;
  for (int32_t i = 0; i < 3; ++i) {
    structs.push_back(
        HasOptionalFieldStruct{i == 0 ? nullptr : fidl::MakeOptional(Int64Struct({i}))});
  }
  EXPECT_TRUE(CheckComparison(structs));
}

TEST(FidlTest, StructWithMultipleFieldsComparison) {
  // Create a vector of structs.
  std::vector<Has2OptionalFieldStruct> structs;
  for (int32_t i = 0; i < 3; i++) {
    for (int32_t j = 0; j < 3; j++) {
      structs.push_back(
          Has2OptionalFieldStruct{i == 0 ? nullptr : fidl::MakeOptional(Int64Struct({i})),
                                  j == 0 ? nullptr : fidl::MakeOptional(Int64Struct({j}))});
    }
  }
  EXPECT_TRUE(CheckComparison(structs));
}

TEST(FidlTest, UnionComparison) {
  // Create a vector of unions.
  std::vector<SimpleUnion> unions;
  SimpleUnion s;
  s.set_i32(0);
  unions.push_back(std::move(s));
  s.set_i32(1);
  unions.push_back(std::move(s));
  s.set_i64(0);
  unions.push_back(std::move(s));
  s.set_i64(1);
  unions.push_back(std::move(s));
  s.set_s({0});
  unions.push_back(std::move(s));
  s.set_s({1});
  unions.push_back(std::move(s));

  EXPECT_TRUE(CheckComparison(unions));
}

TEST(FidlTest, UnionAssignment) {
  SimpleUnion u;
  u.str() = "foo";
  EXPECT_EQ(u.str(), "foo");
  u.i32() = 3;
  EXPECT_EQ(u.i32(), 3);
}

// Build a vector of fidl::VectorPtr, lexicographically sorted given that
// generator generates values ordered by the given index.
template <typename A>
std::vector<fidl::VectorPtr<A>> BuildSortedVector(size_t size,
                                                  const fit::function<A(int32_t)>& generator) {
  constexpr int32_t kNbBaseElement = 3;

  std::vector<fidl::VectorPtr<A>> result;
  result.push_back(fidl::VectorPtr<A>());
  result.push_back(fidl::VectorPtr<A>(std::vector<A>()));
  if (size == 0) {
    return result;
  }
  auto previous = BuildSortedVector(size - 1, generator);
  for (int32_t i = 0; i < kNbBaseElement; ++i) {
    for (const auto& vector : previous) {
      if (!vector) {
        continue;
      }
      std::vector<A> new_vector;
      new_vector.push_back(generator(i));
      for (const auto& value : *vector) {
        new_vector.push_back(fidl::Clone(value));
      }
      result.push_back(std::move(new_vector));
    }
  }
  return result;
}

TEST(FidlTest, TestBuildSortedVector) {
  EXPECT_EQ(2u, BuildSortedVector<uint64_t>(0, [](uint64_t i) { return i; }).size());
  EXPECT_EQ(5u, BuildSortedVector<uint64_t>(1, [](uint64_t i) { return i; }).size());
  EXPECT_EQ(14u, BuildSortedVector<uint64_t>(2, [](uint64_t i) { return i; }).size());
}

TEST(FidlTest, VectorOfIntComparison) {
  // Create a vector of vectors.
  auto vectors = BuildSortedVector<uint32_t>(3, [](uint32_t i) { return i; });
  EXPECT_TRUE(CheckComparison(vectors));
}

TEST(FidlTest, VectorOfStructComparison) {
  // Create a vector of vectors.
  auto vectors = BuildSortedVector<Int64Struct>(3, [](int32_t i) { return Int64Struct{i}; });
  EXPECT_TRUE(CheckComparison(vectors));
}

TEST(FidlTest, VectorOfOptionalStructComparison) {
  // Create a vector of vectors.
  auto vectors = BuildSortedVector<Int64StructPtr>(3, [](int32_t i) {
    return i == 0 ? Int64StructPtr() : fidl::MakeOptional(Int64Struct({i}));
  });
  EXPECT_TRUE(CheckComparison(vectors));
}

// Build a vector of arrays containing distinct values.
template <typename A>
std::vector<std::array<A, 3>> BuildArray(fit::function<A(int32_t)> generator) {
  std::vector<std::array<A, 3>> arrays;
  for (int32_t i = 0; i < 3; ++i) {
    for (int32_t j = 0; j < 3; ++j) {
      for (int32_t k = 0; k < 3; ++k) {
        std::array<A, 3> array;
        array[0] = generator(i);
        array[1] = generator(j);
        array[2] = generator(k);
        arrays.push_back(std::move(array));
      }
    }
  }
  return arrays;
}

TEST(FidlTest, ArrayOfIntComparison) {
  // Create an vector of arrays.
  auto arrays = BuildArray<int32_t>([](int32_t i) { return i; });
  EXPECT_TRUE(CheckComparison(arrays));
}

TEST(FidlTest, ArrayOfStructComparison) {
  // Create an vector of arrays.
  auto arrays = BuildArray<Int64Struct>([](int32_t i) { return Int64Struct{i}; });
  EXPECT_TRUE(CheckComparison(arrays));
}

TEST(FidlTest, ArrayOfOptionalStructComparison) {
  // Create an vector of arrays.
  auto arrays = BuildArray<Int64StructPtr>(
      [](int32_t i) { return i == 0 ? Int64StructPtr() : fidl::MakeOptional(Int64Struct({i})); });
  EXPECT_TRUE(CheckComparison(arrays));
}

}  // namespace
}  // namespace misc
}  // namespace test
}  // namespace fidl
