// 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/ftl/ndm-driver.h>
#include <lib/ftl/volume.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/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() + page_relative_offset * raw_nand->options.page_size,
           original_data.data(), raw_nand->options.page_size);
    memcpy(stitched_oob.data() + 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
