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

#include <fcntl.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/device-watcher/cpp/device-watcher.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/cpp/macros.h>

#include <fbl/unique_fd.h>
#include <ramdevice-client/ramdisk.h>

#include "src/storage/lib/fs_management/cpp/fvm.h"

namespace storage {

constexpr uuid::Uuid kTestPartGUID = {0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
                                      0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};

constexpr uuid::Uuid kTestUniqueGUID = {0xFF, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                                        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

zx::result<> BindFvm(fidl::UnownedClientEnd<fuchsia_device::Controller> device) {
  auto resp = fidl::WireCall(device)->Bind("fvm.cm");
  auto status = zx::make_result(resp.status());
  if (status.is_ok()) {
    if (resp->is_error()) {
      status = zx::make_result(resp->error_value());
    }
  }
  if (status.is_error()) {
    FX_LOGS(ERROR) << "Could not bind disk to FVM driver: " << status.status_string();
    return status.take_error();
  }
  return zx::ok();
}

zx::result<std::string> CreateFvmInstance(const std::string& device_path, size_t slice_size) {
  zx::result device = component::Connect<fuchsia_hardware_block::Block>(device_path);
  if (device.is_error()) {
    return device.take_error();
  }
  if (zx::result status = zx::make_result(fs_management::FvmInit(device.value(), slice_size));
      status.is_error()) {
    FX_LOGS(ERROR) << "Could not format disk with FVM";
    return status.take_error();
  }

  std::string controller_path = device_path + "/device_controller";
  zx::result controller = component::Connect<fuchsia_device::Controller>(controller_path);
  if (controller.is_error()) {
    return controller.take_error();
  }
  if (zx::result status = BindFvm(controller.value()); status.is_error()) {
    return status.take_error();
  }
  std::string fvm_disk_path = device_path + "/fvm";
  if (zx::result channel = device_watcher::RecursiveWaitForFile(fvm_disk_path.c_str(), zx::sec(3));
      channel.is_error()) {
    FX_PLOGS(ERROR, channel.error_value()) << "FVM driver never appeared at " << fvm_disk_path;
    return channel.take_error();
  }

  return zx::ok(fvm_disk_path);
}

zx::result<std::string> CreateFvmPartition(const std::string& device_path, size_t slice_size,
                                           const FvmOptions& options) {
  // Format the raw device to support FVM, and bind the FVM driver to it.
  zx::result<std::string> fvm_disk_path = CreateFvmInstance(device_path, slice_size);
  if (fvm_disk_path.is_error()) {
    return fvm_disk_path.take_error();
  }

  // Open "fvm" driver
  zx::result fvm_client_end =
      component::Connect<fuchsia_hardware_block_volume::VolumeManager>(*fvm_disk_path);
  if (fvm_client_end.is_error()) {
    FX_LOGS(ERROR) << "Could not open FVM driver: " << fvm_client_end.status_string();
    return fvm_client_end.take_error();
  }

  uint64_t slice_count = options.initial_fvm_slice_count;
  uuid::Uuid type_guid = kTestPartGUID;
  if (options.type) {
    type_guid = uuid::Uuid(options.type->data());
  }

  zx::result controller = fs_management::FvmAllocatePartition(
      *fvm_client_end, slice_count, type_guid, kTestUniqueGUID, options.name, 0);
  if (controller.is_error()) {
    FX_LOGS(ERROR) << "Could not allocate FVM partition (slice count: "
                   << options.initial_fvm_slice_count << "): " << controller.status_string();
    return controller.take_error();
  }
  fidl::WireResult result = fidl::WireCall(*controller)->GetTopologicalPath();
  if (!result.ok()) {
    FX_LOGS(ERROR) << "Could not get topological path of fvm partition (fidl error): "
                   << result.FormatDescription();
    return zx::error(result.status());
  }
  fit::result response = *result;
  if (response.is_error()) {
    FX_LOGS(ERROR) << "Could not get topological path of fvm partition: "
                   << zx_status_get_string(response.error_value());
    return zx::error(response.error_value());
  }

  return zx::ok(std::string(response->path.data(), response->path.size()));
}

}  // namespace storage
