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

#include <lib/stdcompat/span.h>
#include <zircon/assert.h>

#include <cstdint>
#include <functional>
#include <iostream>
#include <limits>
#include <optional>
#include <string>
#include <string_view>
#include <utility>

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

#include "src/storage/fvm/format.h"
#include "src/storage/fvm/metadata.h"
#include "src/storage/volume_image/address_descriptor.h"
#include "src/storage/volume_image/fvm/options.h"
#include "src/storage/volume_image/options.h"
#include "src/storage/volume_image/utils/block_utils.h"

namespace storage::volume_image {
namespace {

std::string ToSizeString(uint64_t bytes) {
  constexpr int kByteToMegabyte = 1 << 20;
  std::string size_str = std::to_string(static_cast<double>(bytes) / kByteToMegabyte);
  return size_str.append(" [MB]");
}

}  // namespace

namespace internal {

fvm::Header MakeHeader(const FvmOptions& options, uint64_t slice_count) {
  if (options.max_volume_size.has_value()) {
    return fvm::Header::FromGrowableDiskSize(
        fvm::kMaxUsablePartitions,
        options.target_volume_size.value_or(options.max_volume_size.value()),
        options.max_volume_size.value(), options.slice_size);
  }
  if (options.target_volume_size.has_value()) {
    return fvm::Header::FromDiskSize(fvm::kMaxUsablePartitions, options.target_volume_size.value(),
                                     options.slice_size);
  }
  return fvm::Header::FromSliceCount(fvm::kMaxUsablePartitions, slice_count, options.slice_size);
}

}  // namespace internal

FvmDescriptor::Builder::Builder(FvmDescriptor descriptor)
    : options_(std::move(descriptor.options_)),
      accumulated_slices_(descriptor.slice_count_),
      metadata_allocated_size_(descriptor.metadata_required_size_) {
  for (auto it = descriptor.partitions_.begin(); it != descriptor.partitions_.end();) {
    partitions_.emplace_back(std::move(descriptor.partitions_.extract(it++).value()));
  }
}

FvmDescriptor::Builder& FvmDescriptor::Builder::AddPartition(Partition partition) {
  partitions_.emplace_back(std::move(partition));
  return *this;
}

FvmDescriptor::Builder& FvmDescriptor::Builder::SetOptions(const FvmOptions& options) {
  options_ = options;
  return *this;
}

fpromise::result<FvmDescriptor, std::string> FvmDescriptor::Builder::Build() {
  FvmDescriptor descriptor;

  if (!options_.has_value()) {
    return fpromise::error("FVM Options were not set.");
  }

  if (options_->slice_size == 0) {
    return fpromise::error("FVM's slice_size must be greater than zero.");
  }

  if (options_->max_volume_size.has_value() &&
      options_->max_volume_size.value() < options_->target_volume_size.value_or(0)) {
    std::string error = "FVM's max_volume_size(";
    error.append(ToSizeString(options_->max_volume_size.value()))
        .append(") is smaller than target_volume_size(")
        .append(ToSizeString(options_->target_volume_size.value()))
        .append(").");
    return fpromise::error(error);
  }

  accumulated_slices_ = 0;
  // Check for duplicated partition entries <Name, InstanceGUID> unique pair.
  for (auto& partition : partitions_) {
    auto it = descriptor.partitions_.find(partition);
    if (it != descriptor.partitions_.end()) {
      std::string error = "Partition already exists, could not add partition " +
                          partition.volume().name + " and instance guid " +
                          Guid::ToString(partition.volume().instance).value() +
                          " failed.\n Partition" + it->volume().name + " and instance guid " +
                          Guid::ToString(it->volume().instance).value() + " was added before.";
      partitions_.clear();
      return fpromise::error(error);
    }

    // Update accumulated slice count, and check for overlapping extents.
    std::set<const AddressMap*, std::function<bool(const AddressMap*, const AddressMap*)>> extents(
        [](auto* a, auto* b) { return a->target < b->target; });
    for (const auto& mapping : partition.address().mappings) {
      for (auto it = extents.lower_bound(&mapping); it != extents.end(); ++it) {
        auto* current_extent = *it;
        // We are past the end of the extent.
        if (current_extent->target >= mapping.target + mapping.count) {
          break;
        }

        if (current_extent->target + current_extent->count > mapping.target) {
          // Get the other mapping
          return fpromise::error("Address descriptor of " + partition.volume().name +
                                 " contains overlapping mappings. Conflict between " +
                                 mapping.DebugString() + " and " + current_extent->DebugString());
        }
      }
      extents.insert(&mapping);
      uint64_t required_size = mapping.size.value_or(mapping.count);
      accumulated_slices_ += GetBlockCount(mapping.target, required_size, options_->slice_size);
    }

    descriptor.partitions_.emplace(std::move(partition));
  }
  partitions_.clear();

  fvm::Header header = internal::MakeHeader(*options_, accumulated_slices_);
  metadata_allocated_size_ = 2 * header.GetMetadataAllocatedBytes();

  uint64_t minimum_size = metadata_allocated_size_ + accumulated_slices_ * options_->slice_size;
  // We are not allowed to exceed the  target disk size when set.
  if (minimum_size > options_->target_volume_size.value_or(std::numeric_limits<uint64_t>::max())) {
    std::string error =
        "Failed to build FVMDescriptor. Image does not fit in target volume size. Minimum size "
        "is " +
        ToSizeString(minimum_size) + " and target size is " +
        ToSizeString(options_->target_volume_size.value()) + ".";
    return fpromise::error(error);
  }

  descriptor.metadata_required_size_ = metadata_allocated_size_;
  descriptor.slice_count_ = accumulated_slices_;
  descriptor.options_ = std::move(options_.value());

  return fpromise::ok(std::move(descriptor));
}

fpromise::result<void, std::string> FvmDescriptor::WriteBlockImage(Writer& writer) const {
  fvm::Header header = internal::MakeHeader(options_, slice_count_);

  std::vector<fvm::VPartitionEntry> vpartitions;
  vpartitions.reserve(partitions_.size());

  std::vector<fvm::SliceEntry> slices;
  slices.reserve(slice_count_);

  // Partitions start at index 1.
  size_t current_vpartition = 1;
  for (const auto& partition : partitions()) {
    fvm::VPartitionEntry vpartition = {};
    uint64_t partition_slices = 0;

    memcpy(vpartition.unsafe_name, partition.volume().name.data(), partition.volume().name.size());
    memcpy(vpartition.type, partition.volume().type.data(), partition.volume().type.size());
    memcpy(vpartition.guid, partition.volume().instance.data(), partition.volume().instance.size());
    vpartition.flags = 0;

    for (const auto& mapping : partition.address().mappings) {
      // Slice info for each mapping.
      uint64_t size = std::max(mapping.count, mapping.size.value_or(0));
      uint64_t slice_count = GetBlockCount(mapping.target, size, options_.slice_size);
      partition_slices += slice_count;
      uint64_t start_slice = GetBlockFromBytes(mapping.target, options_.slice_size);

      if (!IsOffsetBlockAligned(mapping.target, options_.slice_size)) {
        return fpromise::error("Partition " + partition.volume().name +
                               " contains unaligned mapping " + std::to_string(mapping.target) +
                               ". FVM Sparse Image requires slice aligned extent |vslice_start|.");
      }

      // Slice entry for each slice in the mapping.
      for (uint64_t vslice_offset = 0; vslice_offset < slice_count; ++vslice_offset) {
        slices.emplace_back(current_vpartition, start_slice + vslice_offset);
      }
    }
    vpartition.slices = safemath::checked_cast<uint32_t>(partition_slices);
    vpartitions.push_back(vpartition);
    current_vpartition++;
  }

  // At this point we've written all the slice contents, now write the metadata.
  auto fvm_metadata_or = fvm::Metadata::Synthesize(header, vpartitions.data(), vpartitions.size(),
                                                   slices.data(), slices.size());
  if (fvm_metadata_or.is_error()) {
    return fpromise::error(
        "FvmDescriptor::WriteBlockImage failed to synthesize fvm metadata with error code : " +
        std::to_string(fvm_metadata_or.status_value()));
  }
  auto fvm_metadata = std::move(fvm_metadata_or.value());

  auto metadata_view = cpp20::span<const uint8_t>(
      reinterpret_cast<const uint8_t*>(fvm_metadata.Get()->data()), fvm_metadata.Get()->size());
  auto metadata_write_result = writer.Write(
      fvm_metadata.GetHeader().GetSuperblockOffset(fvm::SuperblockType::kPrimary), metadata_view);
  if (metadata_write_result.is_error()) {
    return metadata_write_result.take_error_result();
  }

  auto secondary_metadata_write_result = writer.Write(
      fvm_metadata.GetHeader().GetSuperblockOffset(fvm::SuperblockType::kSecondary), metadata_view);
  if (secondary_metadata_write_result.is_error()) {
    return secondary_metadata_write_result.take_error_result();
  }

  // Now write the data for each slice starting at physical slice 1, since it 1-indexed.
  // This is achieved by streaming the data into the slices, in the same order they are read.
  //
  // Slices that are prefilled will have 0, and slices that are allocated but not used will be
  // skipped.
  //
  // In order to guarantee that image has the right size, if the last slice of the image is not
  // written, the last block of the last slice, will be filled with zeroes. This will force the
  // image to have the right size, if its growing dynamically.
  uint64_t current_physical_slice = 1;
  std::vector<uint8_t> slice_buffer;
  slice_buffer.resize(options_.slice_size, 0);

  for (const auto& partition : partitions()) {
    for (const auto& mapping : partition.address().mappings) {
      uint64_t size = std::max(mapping.count, mapping.size.value_or(0));
      uint64_t slice_count = GetBlockCount(mapping.target, size, options_.slice_size);
      uint64_t data_slice_count = GetBlockCount(mapping.target, mapping.count, options_.slice_size);

      // Check if we should fill non data backed slices in this partition mapping explicitly.
      auto fill_value_it = mapping.options.find(EnumAsString(AddressMapOption::kFill));
      std::optional<uint8_t> fill_value = std::nullopt;
      if (fill_value_it != mapping.options.end()) {
        fill_value = static_cast<uint8_t>(fill_value_it->second);
      }
      for (uint64_t slice = 0; slice < slice_count; ++slice) {
        auto slice_data_view = cpp20::span<uint8_t>(slice_buffer);
        if (slice < data_slice_count) {
          // Byte offset of current slice.
          const uint64_t slice_offset = slice * options_.slice_size;
          const uint64_t vslice_offset =
              volume_image::GetBlockFromBytes(mapping.target, options_.slice_size) *
                  options_.slice_size +
              slice_offset;

          // Check if the start of the extent is not aligned with the slice.
          // All extents targets are slice aligned, but that may not be the case when reading
          // from the source.
          const uint64_t data_vslice_start =
              mapping.target > vslice_offset ? mapping.target - vslice_offset : 0;

          // Check if the extent data does not end in slice boundary.
          const uint64_t data_vslice_end = mapping.target + mapping.count - vslice_offset;
          const uint64_t vslice_end = vslice_offset + options_.slice_size - vslice_offset;
          uint64_t data_length = data_vslice_end < vslice_end ? data_vslice_end - data_vslice_start
                                                              : vslice_end - data_vslice_start;
          slice_data_view = slice_data_view.subspan(data_vslice_start, data_length);
          auto read_result = partition.reader()->Read(
              mapping.source + slice_offset + data_vslice_start, slice_data_view);
          if (read_result.is_error()) {
            return read_result.take_error_result();
          }
        }

        // Skip all allocated slices that are not backed by data if we dont need to fill.
        if (slice >= data_slice_count && !fill_value.has_value()) {
          current_physical_slice += slice_count - data_slice_count;
          break;
        }

        // Finally write current slice.
        const uint64_t physical_slice_offset = header.GetSliceDataOffset(current_physical_slice);
        auto write_result = writer.Write(physical_slice_offset, slice_buffer);
        if (write_result.is_error()) {
          return write_result.take_error_result();
        }

        // Clean up the buffer for next read.
        memset(slice_buffer.data(), fill_value.value_or(0), slice_buffer.size());
        current_physical_slice++;
      }
    }
  }
  // Account for slice zero.
  ZX_ASSERT(slices.size() + 1 == current_physical_slice);
  return fpromise::ok();
}

}  // namespace storage::volume_image
