// 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>
// [END imports]

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

// [START device_path]
constexpr char kEduDevicePath[] = "/dev/sys/platform/pt/PCI0/bus/00:06.0_/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]
// Open a FIDL client connection to the examples.qemuedu.Device
fidl::WireSyncClient<examples_qemuedu::Device> OpenDevice() {
  int device = open(kEduDevicePath, 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]
