// 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 <cstdio>
#include <thread>

#include "flutter/fml/macros.h"
#include "flutter/testing/testing.h"
#include "impeller/archivist/archive.h"
#include "impeller/archivist/archive_location.h"
#include "impeller/archivist/archivist_fixture.h"

// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
// NOLINTBEGIN(bugprone-unchecked-optional-access)

namespace impeller {
namespace testing {

static int64_t LastSample = 0;

class Sample : public Archivable {
 public:
  explicit Sample(uint64_t count = 42) : some_data_(count) {}

  Sample(Sample&&) = default;

  uint64_t GetSomeData() const { return some_data_; }

  // |Archivable|
  PrimaryKey GetPrimaryKey() const override { return name_; }

  // |Archivable|
  bool Write(ArchiveLocation& item) const override {
    return item.Write("some_data", some_data_);
  };

  // |Archivable|
  bool Read(ArchiveLocation& item) override {
    name_ = item.GetPrimaryKey();
    return item.Read("some_data", some_data_);
  };

  static const ArchiveDef kArchiveDefinition;

 private:
  uint64_t some_data_;
  PrimaryKey name_ = ++LastSample;

  Sample(const Sample&) = delete;

  Sample& operator=(const Sample&) = delete;
};

const ArchiveDef Sample::kArchiveDefinition = {
    .table_name = "Sample",
    .members = {"some_data"},
};

class SampleWithVector : public Archivable {
 public:
  SampleWithVector() = default;

  // |Archivable|
  PrimaryKey GetPrimaryKey() const override { return std::nullopt; }

  // |Archivable|
  bool Write(ArchiveLocation& item) const override {
    std::vector<Sample> samples;
    for (size_t i = 0; i < 50u; i++) {
      samples.emplace_back(Sample{1988 + i});
    }
    return item.Write("hello", "world") && item.Write("samples", samples);
  };

  // |Archivable|
  bool Read(ArchiveLocation& item) override {
    std::string str;
    auto str_result = item.Read("hello", str);
    std::vector<Sample> samples;
    auto vec_result = item.Read("samples", samples);

    if (!str_result || str != "world" || !vec_result || samples.size() != 50) {
      return false;
    }

    size_t current = 1988;
    for (const auto& sample : samples) {
      if (sample.GetSomeData() != current++) {
        return false;
      }
    }
    return true;
  };

  static const ArchiveDef kArchiveDefinition;

 private:
  std::vector<Sample> samples_;
  SampleWithVector(const SampleWithVector&) = delete;

  SampleWithVector& operator=(const SampleWithVector&) = delete;
};

const ArchiveDef SampleWithVector::kArchiveDefinition = {
    .table_name = "SampleWithVector",
    .members = {"hello", "samples"},
};

using ArchiveTest = ArchivistFixture;

TEST_F(ArchiveTest, SimpleInitialization) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());
}

TEST_F(ArchiveTest, AddStorageClass) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());
}

TEST_F(ArchiveTest, AddData) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());
  Sample sample;
  ASSERT_TRUE(archive.Write(sample));
}

TEST_F(ArchiveTest, AddDataMultiple) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());

  for (size_t i = 0; i < 100; i++) {
    Sample sample(i + 1);
    ASSERT_TRUE(archive.Write(sample));
  }
}

TEST_F(ArchiveTest, ReadData) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());

  size_t count = 50;

  std::vector<PrimaryKey::value_type> keys;
  std::vector<uint64_t> values;

  for (size_t i = 0; i < count; i++) {
    Sample sample(i + 1);
    keys.push_back(sample.GetPrimaryKey().value());
    values.push_back(sample.GetSomeData());
    ASSERT_TRUE(archive.Write(sample));
  }

  for (size_t i = 0; i < count; i++) {
    Sample sample;
    ASSERT_TRUE(archive.Read(keys[i], sample));
    ASSERT_EQ(values[i], sample.GetSomeData());
  }
}

TEST_F(ArchiveTest, ReadDataWithNames) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());

  size_t count = 8;

  std::vector<PrimaryKey::value_type> keys;
  std::vector<uint64_t> values;

  keys.reserve(count);
  values.reserve(count);

  for (size_t i = 0; i < count; i++) {
    Sample sample(i + 1);
    keys.push_back(sample.GetPrimaryKey().value());
    values.push_back(sample.GetSomeData());
    ASSERT_TRUE(archive.Write(sample));
  }

  for (size_t i = 0; i < count; i++) {
    Sample sample;
    ASSERT_TRUE(archive.Read(keys[i], sample));
    ASSERT_EQ(values[i], sample.GetSomeData());
    ASSERT_EQ(keys[i], sample.GetPrimaryKey());
  }
}

TEST_F(ArchiveTest, CanReadWriteVectorOfArchivables) {
  Archive archive(GetArchiveFileName().c_str());
  ASSERT_TRUE(archive.IsValid());

  SampleWithVector sample_with_vector;
  ASSERT_TRUE(archive.Write(sample_with_vector));
  bool read_success = false;
  ASSERT_EQ(
      archive.Read<SampleWithVector>([&](ArchiveLocation& location) -> bool {
        SampleWithVector other_sample_with_vector;
        read_success = other_sample_with_vector.Read(location);
        return true;  // Always keep continuing but assert that we only get one.
      }),
      1u);
  ASSERT_TRUE(read_success);
}

}  // namespace testing
}  // namespace impeller

// NOLINTEND(bugprone-unchecked-optional-access)
