// Copyright 2022 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.

// [START imports]
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <getopt.h>
#include <lib/fdio/directory.h>
#include <libgen.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <filesystem>
// [END imports]

// [START fidl_imports]
#include <fidl/examples.qemuedu/cpp/wire.h>
// [END fidl_imports]

// [START device_path]
constexpr char kDevfsRootPath[] = "/dev/sys/platform";
constexpr char kEduDevicePath[] = "qemu-edu";
// [END device_path]

// [START cli_helpers]
int usage(const char* cmd) {
  fprintf(stderr,
          "\nInteract with the QEMU edu device:\n"
          "   %s live                       Performs a card liveness check\n"
          "   %s fact <n>                   Computes the factorial of n\n"
          "   %s help                       Print this message\n",
          cmd, cmd, cmd);
  return -1;
}

// Returns "true" if the argument matches the prefix.
// In this case, moves the argument past the prefix.
bool prefix_match(const char** arg, const char* prefix) {
  if (!strncmp(*arg, prefix, strlen(prefix))) {
    *arg += strlen(prefix);
    return true;
  }
  return false;
}

constexpr long kBadParse = -1;
long parse_positive_long(const char* number) {
  char* end;
  long result = strtol(number, &end, 10);
  if (end == number || *end != '\0' || result < 0) {
    return kBadParse;
  }
  return result;
}
// [END cli_helpers]

// [START device_client]
// [START_EXCLUDE silent]
// TODO(fxbug.dev/114888): Remove this once we can alias a stable path for generic devices.
// [END_EXCLUDE]
// Search for the device file entry in devfs
std::optional<std::string> SearchDevicePath() {
  for (auto const& dir_entry : std::filesystem::recursive_directory_iterator(kDevfsRootPath)) {
    if (dir_entry.path().string().find(kEduDevicePath) != std::string::npos) {
      return {dir_entry.path()};
    }
  }

  return {};
}

// Open a FIDL client connection to the examples.qemuedu.Device
fidl::WireSyncClient<examples_qemuedu::Device> OpenDevice() {
  auto device_path = SearchDevicePath();
  if (!device_path.has_value()) {
    fprintf(stderr, "Unable to locate qemu-edu device path.\n");
    return {};
  }
  int device = open(device_path.value().c_str(), O_RDWR);

  if (device < 0) {
    fprintf(stderr, "Failed to open qemu edu device: %s\n", strerror(errno));
    return {};
  }

  fidl::ClientEnd<examples_qemuedu::Device> client_end;
  zx_status_t st = fdio_get_service_handle(device, client_end.channel().reset_and_get_address());
  if (st != ZX_OK) {
    fprintf(stderr, "Failed to get service handle: %s\n", zx_status_get_string(st));
    return {};
  }

  return fidl::WireSyncClient(std::move(client_end));
}
// [END device_client]

// [START liveness_check]
// Run a liveness check on the QEMU edu device.
// Returns 0 on success.
int liveness_check() {
  auto client = OpenDevice();
  if (!client.is_valid()) {
    return -1;
  }

  auto liveness_check_result = client->LivenessCheck();
  if (!liveness_check_result.ok()) {
    fprintf(stderr, "Error: failed to get liveness check result: %s\n",
            zx_status_get_string(liveness_check_result.status()));
    return -1;
  }

  if (liveness_check_result->value()->result) {
    printf("Liveness check passed!\n");
    return 0;
  } else {
    printf("Liveness check failed!\n");
    return -1;
  }
}
// [END liveness_check]

// [START compute_factorial]
// Compute the factorial of n using the QEMU edu device.
// Returns 0 on success.
int compute_factorial(long n) {
  auto client = OpenDevice();
  if (!client.is_valid()) {
    return -1;
  }

  if (n >= std::numeric_limits<uint32_t>::max()) {
    fprintf(stderr, "N is too large\n");
    return -1;
  }

  uint32_t input = static_cast<uint32_t>(n);
  auto compute_factorial_result = client->ComputeFactorial(input);
  if (!compute_factorial_result.ok()) {
    fprintf(stderr, "Error: failed to call compute factorial result: %s\n",
            zx_status_get_string(compute_factorial_result.status()));
    return -1;
  }

  printf("Factorial(%u) = %u\n", input, compute_factorial_result->value()->output);

  return 0;
}
// [END compute_factorial]

// [START main]
int main(int argc, char* argv[]) {
  const char* cmd = basename(argv[0]);

  // If no arguments passed, bail out after dumping
  // usage information.
  if (argc < 2) {
    return usage(cmd);
  }

  const char* arg = argv[1];
  if (prefix_match(&arg, "live")) {
    return liveness_check();
  } else if (prefix_match(&arg, "fact")) {
    if (argc < 3) {
      fprintf(stderr, "Expecting 1 argument\n");
      return usage(cmd);
    }
    long n = parse_positive_long(argv[2]);
    return compute_factorial(n);
  }

  return usage(cmd);
}
// [END main]
