// 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 "ftl_raw_nand_image_writer.h"

#include <lib/fpromise/result.h>

#include <cstdint>
#include <iostream>
#include <tuple>
#include <type_traits>

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

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

namespace storage::volume_image {

fpromise::result<std::tuple<FtlRawNandImageWriter, RawNandOptions>, std::string>
FtlRawNandImageWriter::Create(const RawNandOptions& device_options,
                              cpp20::span<const RawNandImageFlag> flags, ImageFormat format,
                              Writer* writer) {
  if (writer == nullptr) {
    return fpromise::error(
        "Failed to created |FtlRawNandImageWriter|. Argument |writer| must be a non null.");
  }

  if (device_options.oob_bytes_size == 0 || device_options.pages_per_block == 0) {
    return fpromise::error(
        "Failed to create |FtlRawNandImageWriter|. Arguments |device_options| must have non zero "
        "|oob_bytes_size| and non-zero |pages_per_block|.");
  }

  RawNandOptions ftl_options = device_options;
  uint32_t multiplier = 1;

  // Find the number of pages to coalesce. Needs to be a divisor of the pages per block, since
  // we can only coalesce pages within the same block.
  while (ftl_options.oob_bytes_size < ftl_image_internal::kFtlMinOobByteSize) {
    // Keep multiplier within block_boundaries.
    do {
      multiplier++;
    } while (device_options.pages_per_block % multiplier != 0 &&
             multiplier <= device_options.pages_per_block);

    if (static_cast<uint32_t>(multiplier) > device_options.pages_per_block) {
      return fpromise::error(
          "FtlRawNandImageWriter failed to create. Not enough spare bytes in block for the FTL.");
    }

    ftl_options.page_size = device_options.page_size * multiplier;
    ftl_options.oob_bytes_size =
        safemath::checked_cast<uint8_t>(device_options.oob_bytes_size * multiplier);
    ftl_options.page_count = device_options.page_count / multiplier;
    ftl_options.pages_per_block = device_options.pages_per_block / multiplier;
  }

  RawNandImageHeader header;
  header.format = format;
  header.page_size = safemath::checked_cast<uint32_t>(device_options.page_size);
  header.oob_size = device_options.oob_bytes_size;
  for (auto flag : flags) {
    header.flags |= static_cast<std::underlying_type<RawNandImageFlag>::type>(flag);
  }

  auto write_result =
      writer->Write(0, cpp20::span<const uint8_t>(reinterpret_cast<const uint8_t*>(&header),
                                                  sizeof(RawNandImageHeader)));
  if (write_result.is_error()) {
    return write_result.take_error_result();
  }

  return fpromise::ok(
      std::make_tuple(FtlRawNandImageWriter(device_options, multiplier, writer), ftl_options));
}

fpromise::result<void, std::string> FtlRawNandImageWriter::Write(uint64_t offset,
                                                                 cpp20::span<const uint8_t> data) {
  uint64_t device_adjusted_page_size = RawNandImageGetAdjustedPageSize(options_);
  uint64_t adjusted_page_size = scale_factor_ * device_adjusted_page_size;
  uint64_t page_offset = offset % adjusted_page_size;
  uint64_t page_number = offset / adjusted_page_size;
  uint64_t physical_page_per_logical = scale_factor_;
  uint64_t base_image_page_offset =
      RawNandImageGetPageOffset(page_number * scale_factor_, options_) + sizeof(RawNandImageHeader);

  // It is a page write.
  if (page_offset == 0) {
    if (data.size() != physical_page_per_logical * options_.page_size) {
      return fpromise::error(
          "FtlRawNandImageWriter requires buffer size match the number of physical pages per "
          "logical page.");
    }

    // Write each page.
    for (uint64_t physical_page_offset = 0; physical_page_offset < physical_page_per_logical;
         ++physical_page_offset) {
      auto relative_physical_page_offset = physical_page_offset * options_.page_size;
      auto physical_page_view = data.subspan(relative_physical_page_offset, options_.page_size);

      auto image_relative_page_offset = physical_page_offset * device_adjusted_page_size;
      auto write_result =
          writer_->Write(base_image_page_offset + image_relative_page_offset, physical_page_view);
      if (write_result.is_error()) {
        return write_result;
      }
    }
    return fpromise::ok();
  }

  // Write each oob area.
  if (page_offset == physical_page_per_logical * options_.page_size) {
    if (data.size() != physical_page_per_logical * options_.oob_bytes_size) {
      return fpromise::error(
          "FtlRawNandImageWriter requires buffer size match the number of physical oob area per "
          "logical oob area per logical page.");
    }

    // Write each page.
    for (uint64_t physical_page_offset = 0; physical_page_offset < physical_page_per_logical;
         ++physical_page_offset) {
      auto relative_physical_page_offset = physical_page_offset * options_.oob_bytes_size;
      auto physical_page_view =
          data.subspan(relative_physical_page_offset, options_.oob_bytes_size);

      auto image_relative_page_oob_offset =
          physical_page_offset * device_adjusted_page_size + options_.page_size;
      auto write_result = writer_->Write(base_image_page_offset + image_relative_page_oob_offset,
                                         physical_page_view);
      if (write_result.is_error()) {
        return write_result;
      }
    }

    return fpromise::ok();
  }

  return fpromise::error(
      "FtlRawNandImageWriter write failed. Unaligned page or unaligned oob write. Actual "
      "offset " +
      std::to_string(page_offset));
}

}  // namespace storage::volume_image
