// 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 "src/storage/volume_image/ftl/ftl_image_internal.h"

#include <lib/stdcompat/span.h>

#include <iostream>
#include <limits>
#include <vector>

#include <fbl/algorithm.h>
#include <safemath/safe_conversions.h>

#include "src/storage/volume_image/ftl/options.h"
#include "src/storage/volume_image/ftl/raw_nand_image_utils.h"

namespace storage::volume_image::ftl_image_internal {
namespace {
// Writes |value| into |sink|, in little endian, as expected by the FTL.
template <typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = true>
void WriteValue(const T value, cpp20::span<uint8_t> sink) {
  for (size_t i = 0; i < sink.size(); ++i) {
    uint8_t byte = (value >> (i * 8)) & 0xFF;
    sink[i] = byte;
  }
}
// Fills |oob_bytes| with the expected FTL data.
void FillOutOfBandBytes(uint32_t logical_page_number, uint32_t generation_number,
                        cpp20::span<uint8_t> oob_bytes) {
  // Reset the contents of |oob| to unprogrammed state.
  std::fill(oob_bytes.begin(), oob_bytes.end(), 0xFF);

  // Mark the block as not bad. This only matters for the first page in the block,
  // but is innocuous in the other pages.
  // Note: Here for clarification.
  oob_bytes[0] = 0xFF;

  // Fill the logical page number.
  WriteValue(logical_page_number, oob_bytes.subspan(1, 4));
  WriteValue(generation_number, oob_bytes.subspan(5, 4));

  // Write the wear count, that has a length of 28 bits.
  // We write the first 3 bytes as is, then write the following most significant 4 bits in the 12-th
  // byte.
  WriteValue(kFtlPageWearCount, oob_bytes.subspan(9, 3));
  oob_bytes[12] = (oob_bytes[12] & 0xF) | ((kFtlPageWearCount >> 20) & 0xF0);

  // Add the NDM marking this page as a valid volume page.
  oob_bytes[15] = kNdmVolumePageMark;
}
}  // namespace

template <>
void WriteOutOfBandBytes<PageType::kVolumePage>(uint32_t logical_page_number,
                                                cpp20::span<uint8_t> oob_bytes) {
  // Volume pages have the generation number ''unprogrammed'' where all bits are set.
  FillOutOfBandBytes(logical_page_number, std::numeric_limits<uint32_t>::max(), oob_bytes);
}

template <>
void WriteOutOfBandBytes<PageType::kMapPage>(uint32_t logical_page_number,
                                             cpp20::span<uint8_t> oob_bytes) {
  // Generated images have the first version of the map pages, with generation number 0.
  FillOutOfBandBytes(logical_page_number, 0, oob_bytes);
}

fpromise::result<void, std::string> WriteMapBlock(
    const std::map<uint32_t, uint32_t>& logical_to_physical_pages,
    const RawNandOptions& ftl_options, uint64_t offset, Writer* writer) {
  if (ftl_options.page_size < 4) {
    return fpromise::error("Page Size must be greater than 4 bytes.");
  }

  if (ftl_options.oob_bytes_size < 16) {
    return fpromise::error("OOB Size must be greater or equal to 16 bytes per page.");
  }

  uint32_t mappings_per_page =
      safemath::checked_cast<uint32_t>(ftl_options.page_size / sizeof(uint32_t));
  uint32_t total_map_pages =
      fbl::round_up(ftl_options.page_count, mappings_per_page) / mappings_per_page;

  std::vector<uint8_t> page_buffer(ftl_options.page_size, 0xFF);
  std::vector<uint8_t> oob_bytes_buffer(ftl_options.oob_bytes_size, 0xFF);

  uint64_t written_pages = 0;
  for (uint32_t map_page_number = 0; map_page_number < total_map_pages; ++map_page_number) {
    std::fill(page_buffer.begin(), page_buffer.end(), 0xFF);
    uint32_t lower_bound = map_page_number * mappings_per_page;
    uint32_t upper_bound = lower_bound + mappings_per_page - 1;
    auto begin = logical_to_physical_pages.lower_bound(lower_bound);
    auto end = logical_to_physical_pages.upper_bound(upper_bound);

    // Fill mappings in this page range.
    for (auto it = begin; it != end; ++it) {
      auto [logical_page, physical_page] = *it;
      size_t mapping_page_offset = logical_page - lower_bound;
      size_t map_page_offset = (mapping_page_offset % mappings_per_page) * sizeof(uint32_t);
      WriteValue(physical_page,
                 cpp20::span<uint8_t>(page_buffer.data() + map_page_offset, sizeof(uint32_t)));
    }

    // Only write map pages that have mappings.
    if (begin == end) {
      continue;
    }

    WriteOutOfBandBytes<PageType::kMapPage>(map_page_number, oob_bytes_buffer);
    auto write_result = RawNandImageWritePage(
        page_buffer, oob_bytes_buffer,
        offset + RawNandImageGetPageOffset(written_pages, ftl_options), writer);
    if (write_result.is_error()) {
      return write_result.take_error_result();
    }
    written_pages++;
  }

  return fpromise::ok();
}

}  // namespace storage::volume_image::ftl_image_internal
