// Copyright 2018 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 <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.fshost/cpp/wire.h>
#include <fidl/fuchsia.hardware.block/cpp/wire.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <getopt.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/service/llcpp/service.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/device/block.h>
#include <zircon/types.h>

#include <string>
#include <utility>

#include <fbl/unique_fd.h>
#include <storage-metrics/block-metrics.h>

#include "src/storage/fshost/constants.h"

namespace {

namespace fio = fuchsia_io;

int Usage() {
  fprintf(stdout, "usage: storage-metrics [ <option>* ] [paths]\n");
  fprintf(stdout, "storage-metrics reports metrics for block devices\n");
  fprintf(stdout, " --clear : clears metrics on block devices supporting paths\n");
  fprintf(stdout, " --help : Show this help message\n");
  return -1;
}

struct StorageMetricOptions {
  // True indicates that a call to retrieve block device metrics should also clear those metrics.
  bool clear_block = false;
};

void PrintBlockMetrics(const char* dev, const fuchsia_hardware_block::wire::BlockStats& stats) {
  printf("Block Metrics for device path: %s\n", dev);
  storage_metrics::BlockDeviceMetrics metrics(&stats);
  metrics.Dump(stdout);
}

// Retrieves metrics for the block device at dev. Clears metrics if clear is true.
zx::status<fuchsia_hardware_block::wire::BlockStats> GetBlockStats(const char* dev, bool clear) {
  auto client_end = service::Connect<fuchsia_hardware_block::Block>(dev);
  if (!client_end.is_ok()) {
    return client_end.take_error();
  }
  fidl::WireSyncClient client(std::move(client_end.value()));

  auto result = client->GetStats(clear);
  zx_status_t status = !result.ok() ? result.error().status() : result.value().status;

  if (status != ZX_OK) {
    fprintf(stderr, "Error getting stats for %s: %s\n", dev, zx_status_get_string(status));
    return zx::error(status);
  }

  return zx::ok(*result.value().stats);
}

void ParseCommandLineArguments(int argc, char** argv, StorageMetricOptions* options) {
  static const struct option opts[] = {
      {"clear", optional_argument, NULL, 'c'},
      {"help", no_argument, NULL, 'h'},
      {0, 0, 0, 0},
  };
  for (int opt; (opt = getopt_long(argc, argv, "c::e::h", opts, nullptr)) != -1;) {
    switch (opt) {
      case 'c':
        options->clear_block = (optarg == nullptr || strcmp(optarg, "true") == 0);
        break;
      case 'h':
        __FALLTHROUGH;
      default:
        Usage();
    }
  }
}

// Retrieves and prints metrics for the block device associated with the filesystem at path.
void RunBlockMetrics(const char* path, const StorageMetricOptions options) {
  fbl::unique_fd fd(open(path, O_RDONLY));
  if (!fd) {
    fd.reset(open(path, O_RDONLY));
    if (!fd) {
      fprintf(stderr, "storage-metrics could not open target: %s, errno %d (%s)\n", path, errno,
              strerror(errno));
      return;
    }
  }

  std::string device_path;
  fdio_cpp::FdioCaller caller(std::move(fd));
  auto result = fidl::WireCall(caller.directory())->QueryFilesystem();
  if (result.ok() && result.value().s == ZX_OK) {
    std::string fshost_path(fshost::kHubAdminServicePath);
    auto fshost_or = service::Connect<fuchsia_fshost::Admin>(fshost_path.c_str());
    if (fshost_or.is_error()) {
      fprintf(stderr, "Error connecting to fshost (@ %s): %s\n", fshost_path.c_str(),
              fshost_or.status_string());
    } else {
      auto path_result = fidl::WireCall(*fshost_or)->GetDevicePath(result.value().info->fs_id);
      if (path_result.ok() && path_result->is_ok()) {
        device_path = std::string(path_result->value()->path.get());
      }
    }
  }

  if (!device_path.empty()) {
    zx::status<fuchsia_hardware_block::wire::BlockStats> block_stats =
        GetBlockStats(device_path.data(), options.clear_block);
    if (block_stats.is_ok()) {
      PrintBlockMetrics(device_path.data(), *block_stats);
    } else {
      fprintf(stderr, "storage-metrics could not retrieve block metrics for %s: %s\n", path,
              block_stats.status_string());
    }
  } else {
    // Maybe this is not a filesystem. See if this happens to be a block device.
    // TODO(auradkar): We need better args parsing to consider fs and block
    // device seperately.
    zx::status<fuchsia_hardware_block::wire::BlockStats> block_stats =
        GetBlockStats(path, options.clear_block);
    if (!block_stats.is_ok()) {
      fprintf(stderr, "storage-metrics could not retrieve block metrics for %s: %s\n", path,
              block_stats.status_string());
    } else {
      PrintBlockMetrics(path, *block_stats);
    }
  }
}

}  // namespace

int main(int argc, char** argv) {
  StorageMetricOptions options;
  ParseCommandLineArguments(argc, argv, &options);
  // Iterate through the remaining arguments, which are all paths
  for (int i = optind; i < argc; i++) {
    char* path = argv[i];

    printf("Metrics for: %s\n", path);
    RunBlockMetrics(path, options);
    printf("\n");
  }

  return 0;
}
