// Copyright 2020 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 <lib/fpromise/result.h>
#include <lib/stdcompat/span.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/ref_ptr.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/storage/lib/ftl/ftln/ndm-driver.h"
#include "src/storage/lib/ftl/ftln/volume.h"
#include "src/storage/volume_image/address_descriptor.h"
#include "src/storage/volume_image/ftl/ftl_image.h"
#include "src/storage/volume_image/ftl/ftl_raw_nand_image_writer.h"
#include "src/storage/volume_image/ftl/ftl_test_helper.h"
#include "src/storage/volume_image/ftl/options.h"
#include "src/storage/volume_image/ftl/raw_nand_image.h"
#include "src/storage/volume_image/ftl/raw_nand_image_utils.h"
#include "src/storage/volume_image/partition.h"
#include "src/storage/volume_image/utils/block_utils.h"
#include "src/storage/volume_image/utils/reader.h"
#include "src/storage/volume_image/utils/writer.h"
#include "src/storage/volume_image/volume_descriptor.h"

namespace storage::volume_image {
namespace {

constexpr uint64_t kBlockSize = 4096;
static_assert(kBlockSize % 4 == 0, "Blocks must be 32-bit aligned to simplify content generation.");

constexpr uint64_t kPageSize = 8192;
constexpr uint32_t kOobBytesSize = 16;
constexpr uint64_t kPagesPerBlock = 32;
constexpr uint64_t kBlockCount = 20;

RawNandOptions GetOptions() {
  RawNandOptions options;
  options.oob_bytes_size = kOobBytesSize;
  options.page_size = kPageSize;
  options.pages_per_block = kPagesPerBlock;
  options.page_count = kPagesPerBlock * kBlockCount;
  return options;
}

// This test provides proof of concept and verifies that an image generated by the the FtlImageWrite
// interface, allows the FTL driver to bootstrap.
//
//
// The first test, checks that the default image, without adjusting page size will be loaded.
// TODO(gevalentino): Once the respective logic is added, the following tests must be added.
//
//     * The third test, verifies that the FVM in the FTL image is bootstrapped
//     appropriately, by the FTL driver.
//
//  This is tracked as part of the  FTL image generation stack.

void FillBlock(uint32_t block_number, size_t block_offset, cpp20::span<uint8_t> block_view) {
  uint8_t* content = reinterpret_cast<uint8_t*>(&block_number);

  for (size_t i = 0; i < block_view.size(); ++i) {
    block_view[i] = content[(block_offset + i) % 4];
  }
}

// This reader provides the contents to be written into the image.
// Each block consists of repeated 32 bit integers containing the block number.
// Each block is of |kBlockSize|.
class FakeContentReader final : public Reader {
 public:
  uint64_t length() const override { return 0; }

  fpromise::result<void, std::string> Read(uint64_t offset,
                                           cpp20::span<uint8_t> buffer) const final {
    // Calculate the block the offset is in.
    uint32_t first_block = static_cast<uint32_t>(GetBlockFromBytes(offset, kBlockSize));
    uint64_t offset_from_first_block = GetOffsetFromBlockStart(offset, kBlockSize);
    uint64_t read_bytes = 0;
    auto first_block_view = buffer.subspan(0, kBlockSize - offset_from_first_block);
    FillBlock(first_block, offset_from_first_block, first_block_view);
    read_bytes += first_block_view.size();

    // Remaining blocks are aligned.
    uint64_t block_count = GetBlockCount(offset, buffer.size(), kBlockSize);

    for (uint64_t current_block = first_block + 1; current_block < first_block + block_count;
         ++current_block) {
      size_t length = std::min(kBlockSize, buffer.size() - read_bytes);
      auto block_view = buffer.subspan(read_bytes, length);
      FillBlock(static_cast<uint32_t>(current_block), 0, block_view);
      read_bytes += block_view.size();
    }

    return fpromise::ok();
  }
};

class InMemoryWriter final : public Writer {
 public:
  explicit InMemoryWriter(InMemoryRawNand* raw_nand) : raw_nand_(raw_nand) {}

  fpromise::result<void, std::string> Write(uint64_t offset,
                                            cpp20::span<const uint8_t> buffer) final {
    // Calculate page number based on adjusted offset.
    uint64_t adjusted_page_size = RawNandImageGetAdjustedPageSize(raw_nand_->options);
    uint32_t page_number = static_cast<uint32_t>(offset / adjusted_page_size);
    // Check if its OOB or page data based on the offset.
    if (offset % adjusted_page_size == 0) {
      auto page_view = buffer.subspan(0, raw_nand_->options.page_size);
      raw_nand_->page_data[page_number] = std::vector<uint8_t>(page_view.begin(), page_view.end());
    } else if (offset % adjusted_page_size == raw_nand_->options.page_size) {
      auto oob_view = buffer.subspan(0, raw_nand_->options.oob_bytes_size);
      raw_nand_->page_oob[page_number] = std::vector<uint8_t>(oob_view.begin(), oob_view.end());
    } else {
      return fpromise::error("Invalid Offset.");
    }

    return fpromise::ok();
  }

 private:
  InMemoryRawNand* raw_nand_ = nullptr;
};

class FakeFtl final : public ftl::FtlInstance {
 public:
  bool OnVolumeAdded(uint32_t page_size, uint32_t num_pages) final { return true; }
};

Partition MakePartition() {
  VolumeDescriptor volume_descriptor;
  volume_descriptor.name = "Hello Partition";
  volume_descriptor.block_size = 8192;

  AddressDescriptor address_descriptor;
  address_descriptor.mappings = {
      {.source = 512,
       .target = 8192,
       .count = 4096,
       .size = 4096,
       .options = {std::make_pair(EnumAsString(AddressMapOption::kFill), 0)}},
      {.source = 10002,
       .target = 0,
       .count = 0,
       .size = 8192,
       .options = {std::make_pair(EnumAsString(AddressMapOption::kFill), 0)}},
      {.source = 20000, .target = 81920, .count = 81920},
  };

  return Partition(std::move(volume_descriptor), std::move(address_descriptor),
                   std::make_unique<FakeContentReader>());
}

class FtlEnvironment : public ::testing::Environment {
  void SetUp() override { ftl::InitModules(); }
};

[[maybe_unused]] auto* environment = testing::AddGlobalTestEnvironment(new FtlEnvironment());

TEST(FtlImageBootstrapTest, FtlDriverBootstrapsFromImageIsOk) {
  [[maybe_unused]] auto partition = MakePartition();
  std::unique_ptr<InMemoryRawNand> raw_nand = std::make_unique<InMemoryRawNand>();
  raw_nand->options = GetOptions();

  InMemoryWriter writer(raw_nand.get());
  auto image_write_result = FtlImageWrite(raw_nand->options, partition, &writer);

  std::unique_ptr<InMemoryNdm> ndm_driver =
      std::make_unique<InMemoryNdm>(raw_nand.get(), kPageSize, kOobBytesSize);
  FakeFtl fake_ftl;
  ftl::VolumeImpl ftl_volume(&fake_ftl);
  const char* result = ftl_volume.Init(std::move(ndm_driver));
  ASSERT_EQ(result, nullptr) << result;

  // First mapping.
  std::vector<uint8_t> page_buffer(raw_nand->options.page_size, 0xFF);
  ASSERT_EQ(ftl_volume.Read(1, 1, page_buffer.data()), ZX_OK);

  std::vector<uint8_t> expected_page_buffer(raw_nand->options.page_size, 0xFF);
  ASSERT_TRUE(partition.reader()->Read(512, expected_page_buffer).is_ok());

  EXPECT_THAT(
      cpp20::span<uint8_t>(page_buffer).subspan(0, 4096),
      testing::ElementsAreArray(cpp20::span<uint8_t>(expected_page_buffer).subspan(0, 4096)));
  // Remainder of a mapping fitting on the same page, is filled with zeroes.
  EXPECT_THAT(cpp20::span<uint8_t>(page_buffer).subspan(4096, 4096), testing::Each(testing::Eq(0)));

  // Second mapping.
  ASSERT_EQ(ftl_volume.Read(0, 1, page_buffer.data()), ZX_OK);
  EXPECT_THAT(cpp20::span<uint8_t>(page_buffer).subspan(0, 8192), testing::Each(testing::Eq(0)));

  // Third mapping.
  std::fill(expected_page_buffer.begin(), expected_page_buffer.end(), 0);
  std::fill(page_buffer.begin(), page_buffer.end(), 0xFF);
  expected_page_buffer.resize(81920, 0);
  page_buffer.resize(81920, 0xFF);
  ASSERT_TRUE(partition.reader()->Read(20000, expected_page_buffer).is_ok());

  ASSERT_EQ(ftl_volume.Read(10, 10, page_buffer.data()), ZX_OK);
  EXPECT_THAT(page_buffer, testing::ElementsAreArray(expected_page_buffer));
}

// Stitches pages in |raw_nand| into bigger pages, such that page | 2i | 2i + 1| is page content for
// |page i| and same applies for OOB bytes. In the example, |logical_pages_per_physical_pages| is 2.
std::unique_ptr<InMemoryRawNand> CombinePages(uint32_t logical_pages_per_physical_pages,
                                              std::unique_ptr<InMemoryRawNand> raw_nand) {
  std::unique_ptr<InMemoryRawNand> stitched_raw_nand = std::make_unique<InMemoryRawNand>();
  stitched_raw_nand->options = raw_nand->options;
  stitched_raw_nand->options.oob_bytes_size *= logical_pages_per_physical_pages;
  stitched_raw_nand->options.page_size *= logical_pages_per_physical_pages;
  stitched_raw_nand->options.pages_per_block /= logical_pages_per_physical_pages;
  stitched_raw_nand->options.page_count /= logical_pages_per_physical_pages;

  for (auto [key, _] : raw_nand->page_data) {
    uint32_t page_number = key / logical_pages_per_physical_pages;
    uint32_t page_relative_offset = key % logical_pages_per_physical_pages;

    const auto& original_data = raw_nand->page_data[key];
    const auto& original_oob = raw_nand->page_oob[key];

    if (stitched_raw_nand->page_data.find(page_number) == stitched_raw_nand->page_data.end()) {
      stitched_raw_nand->page_data[page_number].resize(stitched_raw_nand->options.page_size, 0xFF);
      stitched_raw_nand->page_oob[page_number].resize(stitched_raw_nand->options.oob_bytes_size,
                                                      0xFF);
    }

    auto& stitched_data = stitched_raw_nand->page_data[page_number];
    auto& stitched_oob = stitched_raw_nand->page_oob[page_number];

    memcpy(stitched_data.data() +
               static_cast<size_t>(page_relative_offset) * raw_nand->options.page_size,
           original_data.data(), raw_nand->options.page_size);
    memcpy(stitched_oob.data() +
               static_cast<size_t>(page_relative_offset) * raw_nand->options.oob_bytes_size,
           original_oob.data(), raw_nand->options.oob_bytes_size);
  }

  return stitched_raw_nand;
}

class InMemoryWriterWithHeader : public Writer {
 public:
  explicit InMemoryWriterWithHeader(InMemoryWriter* writer) : writer_(writer) {}

  fpromise::result<void, std::string> Write(uint64_t offset,
                                            cpp20::span<const uint8_t> buffer) final {
    if (offset < sizeof(RawNandImageHeader)) {
      size_t leading_header_bytes =
          std::min(static_cast<size_t>(sizeof(RawNandImageHeader) - offset), buffer.size());
      memcpy(reinterpret_cast<uint8_t*>(&header_) + offset, buffer.data(), leading_header_bytes);
      if (leading_header_bytes == buffer.size()) {
        return fpromise::ok();
      }
      buffer.subspan(leading_header_bytes);
      offset = sizeof(RawNandImageHeader);
    }

    return writer_->Write(offset - sizeof(RawNandImageHeader), buffer);
  }

  const auto& header() { return header_; }

 private:
  RawNandImageHeader header_;
  InMemoryWriter* writer_ = nullptr;
};

TEST(FtlImageBootstrapTest, FtlDriverBootstrapsFromImageWithPageDoubleIsOk) {
  [[maybe_unused]] auto partition = MakePartition();
  std::unique_ptr<InMemoryRawNand> raw_nand = std::make_unique<InMemoryRawNand>();
  auto options = GetOptions();
  options.oob_bytes_size /= 2;
  options.page_size /= 2;
  options.page_count *= 2;
  options.pages_per_block *= 2;
  raw_nand->options = options;

  InMemoryWriter data_writer(raw_nand.get());
  InMemoryWriterWithHeader writer(&data_writer);

  std::vector<RawNandImageFlag> flags = {RawNandImageFlag::kRequireWipeBeforeFlash};
  auto ftl_raw_nand_image_writer_result =
      FtlRawNandImageWriter::Create(options, flags, ImageFormat::kRawImage, &writer);
  ASSERT_TRUE(ftl_raw_nand_image_writer_result.is_ok()) << ftl_raw_nand_image_writer_result.error();
  auto [ftl_raw_nand_image_writer, ftl_options] = ftl_raw_nand_image_writer_result.take_value();

  auto image_write_result = FtlImageWrite(ftl_options, partition, &ftl_raw_nand_image_writer);
  ASSERT_TRUE(image_write_result.is_ok()) << image_write_result.error();

  auto stitched_raw_nand = CombinePages(2, std::move(raw_nand));

  std::unique_ptr<InMemoryNdm> ndm_driver =
      std::make_unique<InMemoryNdm>(stitched_raw_nand.get(), kPageSize, kOobBytesSize);
  FakeFtl fake_ftl;
  ftl::VolumeImpl ftl_volume(&fake_ftl);
  const char* result = ftl_volume.Init(std::move(ndm_driver));
  ASSERT_EQ(result, nullptr) << result;

  // First mapping.
  std::vector<uint8_t> page_buffer(stitched_raw_nand->options.page_size, 0xFF);
  ASSERT_EQ(ftl_volume.Read(1, 1, page_buffer.data()), ZX_OK);

  std::vector<uint8_t> expected_page_buffer(stitched_raw_nand->options.page_size, 0xFF);
  ASSERT_TRUE(partition.reader()->Read(512, expected_page_buffer).is_ok());

  EXPECT_THAT(
      cpp20::span<uint8_t>(page_buffer).subspan(0, 4096),
      testing::ElementsAreArray(cpp20::span<uint8_t>(expected_page_buffer).subspan(0, 4096)));
  // Remainder of a mapping fitting on the same page, is filled with zeroes.
  EXPECT_THAT(cpp20::span<uint8_t>(page_buffer).subspan(4096, 4096), testing::Each(testing::Eq(0)));

  // Second mapping.
  ASSERT_EQ(ftl_volume.Read(0, 1, page_buffer.data()), ZX_OK);
  EXPECT_THAT(cpp20::span<uint8_t>(page_buffer).subspan(0, 8192), testing::Each(testing::Eq(0)));

  // Third mapping.
  std::fill(expected_page_buffer.begin(), expected_page_buffer.end(), 0);
  std::fill(page_buffer.begin(), page_buffer.end(), 0xFF);
  expected_page_buffer.resize(81920, 0);
  page_buffer.resize(81920, 0xFF);
  ASSERT_TRUE(partition.reader()->Read(20000, expected_page_buffer).is_ok());

  ASSERT_EQ(ftl_volume.Read(10, 10, page_buffer.data()), ZX_OK);
  EXPECT_THAT(page_buffer, testing::ElementsAreArray(expected_page_buffer));
}

}  // namespace
}  // namespace storage::volume_image
