// Copyright 2021 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 <fcntl.h>
#include <lib/fit/defer.h>
#include <lib/fpromise/result.h>
#include <string.h>
#include <unistd.h>

#include <charconv>
#include <cstdint>
#include <filesystem>
#include <iostream>
#include <limits>
#include <memory>
#include <string>

#include <fbl/unique_fd.h>

#include "src/storage/fvm/format.h"
#include "src/storage/volume_image/adapter/blobfs_partition.h"
#include "src/storage/volume_image/adapter/commands.h"
#include "src/storage/volume_image/adapter/empty_partition.h"
#include "src/storage/volume_image/adapter/minfs_partition.h"
#include "src/storage/volume_image/address_descriptor.h"
#include "src/storage/volume_image/fvm/fvm_descriptor.h"
#include "src/storage/volume_image/fvm/fvm_image_extend.h"
#include "src/storage/volume_image/fvm/fvm_sparse_image.h"
#include "src/storage/volume_image/fvm/options.h"
#include "src/storage/volume_image/options.h"
#include "src/storage/volume_image/partition.h"
#include "src/storage/volume_image/utils/bounded_writer.h"
#include "src/storage/volume_image/utils/fd_reader.h"
#include "src/storage/volume_image/utils/fd_writer.h"
#include "src/storage/volume_image/utils/lz4_compressor.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 {

std::string Errno() { return std::string(strerror(errno)); }

class ZeroReader final : public Reader {
  uint64_t length() const final { return std::numeric_limits<uint64_t>::max(); }

  fpromise::result<void, std::string> Read(uint64_t offset,
                                           cpp20::span<uint8_t> buffer) const final {
    memset(buffer.data(), '0', buffer.size());
    return fpromise::ok();
  }
};

fpromise::result<Partition, std::string> ProcessPartition(const PartitionParams& params,
                                                          const FvmOptions& fvm_options) {
  Partition partition;

  std::unique_ptr<Reader> volume_reader;
  if (params.format != PartitionImageFormat::kEmptyPartition) {
    auto volume_reader_or = FdReader::Create(params.source_image_path);
    if (volume_reader_or.is_error()) {
      return volume_reader_or.take_error_result();
    }
    volume_reader = std::make_unique<FdReader>(volume_reader_or.take_value());
  }

  switch (params.format) {
    case PartitionImageFormat::kBlobfs: {
      auto partition_or =
          CreateBlobfsFvmPartition(std::move(volume_reader), params.options, fvm_options);
      if (partition_or.is_error()) {
        return partition_or.take_error_result();
      }
      partition = std::move(partition_or.value());
      break;
    }

    case PartitionImageFormat::kMinfs: {
      auto partition_or =
          CreateMinfsFvmPartition(std::move(volume_reader), params.options, fvm_options);
      if (partition_or.is_error()) {
        return partition_or.take_error_result();
      }
      partition = std::move(partition_or.value());
      break;
    }

    case PartitionImageFormat::kEmptyPartition: {
      auto partition_or = CreateEmptyFvmPartition(params.options, fvm_options);
      if (partition_or.is_error()) {
        return partition_or.take_error_result();
      }
      partition = partition_or.take_value();
    } break;

    default:
      return fpromise::error("Unknown Partition format.");
  }

  // At this point we have a default Minfs or Blobfs partition, but we need to adjust it.
  if (!params.label.empty()) {
    partition.volume().name = params.label;
  }

  if (params.type_guid.has_value()) {
    partition.volume().type = params.type_guid.value();
  }

  if (params.encrypted) {
    partition.volume().encryption = EncryptionType::kZxcrypt;
  } else {
    partition.volume().encryption = EncryptionType::kNone;
  }

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

fpromise::result<void, std::string> CompressFile(std::string_view input, std::string_view output) {
  auto input_reader_or = FdReader::Create(input);
  if (input_reader_or.is_error()) {
    return input_reader_or.take_error_result();
  }
  auto input_reader = input_reader_or.take_value();

  std::string output_tmp = std::string(output) + ".lz4.tmp";
  auto remove_temp_file = fit::defer([&output_tmp]() { unlink(output_tmp.c_str()); });
  // Clean up any existing remainders from previous run if it wasnt cleaned up properly.
  unlink(output_tmp.c_str());

  // Create a temporary file to compress into, just in case, input == output.
  fbl::unique_fd output_tmp_fd(open(output_tmp.c_str(), O_CREAT | O_WRONLY, 0644));
  if (!output_tmp_fd.is_valid()) {
    auto err = Errno();
    return fpromise::error("Failed to create temporary file at " + output_tmp +
                           "for decompression. More specifically: " + err + ".");
  }

  auto compression_writer_or = FdWriter::Create(output_tmp.c_str());
  if (compression_writer_or.is_error()) {
    return compression_writer_or.take_error_result();
  }
  auto compression_writer = compression_writer_or.take_value();

  // Now stream the contents of the input file.
  uint64_t read_bytes = 0;

  // 1 MB buffer size.
  constexpr uint64_t kMaxBufferSize = 1 << 20;
  std::vector<uint8_t> read_buffer;
  read_buffer.resize(kMaxBufferSize, 0);

  // Initialize the compressor
  CompressionOptions options;
  options.schema = CompressionSchema::kLz4;
  auto compressor_or = Lz4Compressor::Create(options);
  if (compressor_or.is_error()) {
    return compressor_or.take_error_result();
  }
  auto compressor = compressor_or.take_value();
  uint64_t written_bytes = 0;

  compressor.Prepare(
      [&compression_writer, &written_bytes](auto buffer) -> fpromise::result<void, std::string> {
        if (auto result = compression_writer.Write(written_bytes, buffer); result.is_error()) {
          return result;
        }
        written_bytes += buffer.size();
        return fpromise::ok();
      });
  while (read_bytes < input_reader.length()) {
    auto read_view =
        cpp20::span<uint8_t>(read_buffer)
            .subspan(0, std::min(kMaxBufferSize,
                                 static_cast<uint64_t>(input_reader.length() - read_bytes)));
    if (auto result = input_reader.Read(read_bytes, read_view); result.is_error()) {
      return result;
    }
    read_bytes += read_view.size();

    if (auto compress_result = compressor.Compress(read_view); compress_result.is_error()) {
      return compress_result;
    }
  }

  if (auto compress_result = compressor.Finalize(); compress_result.is_error()) {
    return compress_result;
  }

  // Move the temporary output into the primary one.
  if (auto result = rename(output_tmp.c_str(), std::string(output).c_str()); result == -1) {
    auto err = Errno();
    return fpromise::error("Failed to move temporary compressed file " + output_tmp +
                           " to final location " + std::string(output) +
                           ". More specifically: " + err + ".");
  }

  return fpromise::ok();
}

}  // namespace

fpromise::result<void, std::string> Create(const CreateParams& params) {
  if (params.output_path.empty()) {
    return fpromise::error("No image output path provided for Create.");
  }

  if (params.is_output_embedded) {
    if (!params.offset.has_value()) {
      return fpromise::error("Must provide offset for embedding fvm image.");
    }

    if (!params.length.has_value()) {
      return fpromise::error("Must provide length for embedding fvm image.");
    }
  }

  if (params.fvm_options.slice_size == 0) {
    return fpromise::error("Slice size must be greater than zero.");
  }

  if (params.fvm_options.slice_size % fvm::kBlockSize != 0) {
    return fpromise::error("Slice size must be a multiple of fvm's block size(" +
                           std::to_string(fvm::kBlockSize >> 10) + " KB).");
  }

  // When not embedded, clean up any existing file under such name.
  if (!params.is_output_embedded) {
    unlink(params.output_path.c_str());
  }

  fbl::unique_fd output_fd(open(params.output_path.c_str(), O_CREAT | O_WRONLY, 0644));
  if (!output_fd.is_valid()) {
    return fpromise::error("Opening output file failed. More specifically: " + Errno() + ".");
  }

  // If is not embedded then truncate the file.
  if (!params.is_output_embedded && params.fvm_options.target_volume_size.has_value()) {
    if (ftruncate(output_fd.get(),
                  static_cast<off_t>(params.fvm_options.target_volume_size.value())) == -1) {
      return fpromise::error("Failed to truncate " + params.output_path + " to length " +
                             std::to_string(params.fvm_options.target_volume_size.value()) +
                             ". More specifically: " + Errno() + ".");
    }
  }

  std::unique_ptr<Writer> writer = std::make_unique<FdWriter>(std::move(output_fd));
  // If we are embedding somewhere, make it so the writers errors out if someone attempts
  // to write out of the designated area.
  if (params.is_output_embedded) {
    writer = std::make_unique<BoundedWriter>(std::move(writer), params.offset.value(),
                                             params.length.value());
  }

  FvmDescriptor::Builder builder;
  builder.SetOptions(params.fvm_options);

  for (const auto& partition_param : params.partitions) {
    auto partition_or = ProcessPartition(partition_param, params.fvm_options);
    if (partition_or.is_error()) {
      return partition_or.take_error_result();
    }
    builder.AddPartition(partition_or.take_value());
  }

  auto descriptor_or = builder.Build();
  if (descriptor_or.is_error()) {
    return descriptor_or.take_error_result();
  }
  auto descriptor = descriptor_or.take_value();

  switch (params.format) {
    case FvmImageFormat::kBlockImage:
      if (auto result = descriptor.WriteBlockImage(*writer); result.is_error()) {
        return result.take_error_result();
      }

      if (params.trim_image) {
        auto output_reader_or = FdReader::Create(params.output_path);
        if (output_reader_or.is_error()) {
          return output_reader_or.take_error_result();
        }
        // Calculate the trim size.
        auto trim_size_or = FvmImageGetTrimmedSize(output_reader_or.value());
        if (trim_size_or.is_error()) {
          return trim_size_or.take_error_result();
        }
        if (truncate(params.output_path.c_str(),
                     static_cast<off_t>(params.offset.value_or(0)) + trim_size_or.value()) == -1) {
          return fpromise::error("Resize to fit image failed. Trimming " + params.output_path +
                                 " to length " + std::to_string(trim_size_or.value()) +
                                 ". More specifically: " + Errno() + ".");
        }
      }

      if (params.fvm_options.compression.schema != CompressionSchema::kNone) {
        return CompressFile(params.output_path, params.output_path);
      }

      return fpromise::ok();

    case FvmImageFormat::kSparseImage:
      std::unique_ptr<Compressor> compressor = nullptr;
      if (params.fvm_options.compression.schema != CompressionSchema::kNone) {
        auto compressor_or = Lz4Compressor::Create(params.fvm_options.compression);
        if (compressor_or.is_error()) {
          return compressor_or.take_error_result();
        }
        compressor = std::make_unique<Lz4Compressor>(compressor_or.take_value());
      }
      if (auto result = FvmSparseWriteImage(descriptor, writer.get(), compressor.get());
          result.is_error()) {
        return result.take_error_result();
      }
      break;
  }

  return fpromise::ok();
}

}  // namespace storage::volume_image
