// 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 <cstdint>
#include <functional>
#include <limits>
#include <string>
#include <string_view>
#include <utility>

#include <fbl/algorithm.h>

#include "src/storage/fvm/format.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 = 2 << 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::FromDiskSize(fvm::kMaxUsablePartitions, 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;
}

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

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

  if (options_->slice_size == 0) {
    return fit::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 fit::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 fit::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 fit::error("Address descriptor of " + partition.volume().name +
                            " contains overlapping mappings. Conflict between " +
                            mapping.DebugString() + " and " + current_extent->DebugString());
        }
      }
      extents.insert(&mapping);
      accumulated_slices_ += GetBlockCount(mapping.target, mapping.count, 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 fit::error(error);
  }

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

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

}  // namespace storage::volume_image
