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

#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <fidl/fuchsia.hardware.qemuedu/cpp/wire.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>

constexpr char kEduDevicePath[] =
    "/dev/sys/platform/platform-passthrough/PCI0/bus/00:06.0_/qemu-edu";
constexpr char kEduDevicePath2[] =
    "/dev/sys/platform/platform-passthrough/acpi/acpi-KBLT/qemu-edu";

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;
}

fidl::WireSyncClient<fuchsia_hardware_qemuedu::Device> OpenDevice() {
  int device = open(kEduDevicePath, O_RDWR);

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

  fidl::ClientEnd<fuchsia_hardware_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::BindSyncClient(std::move(client_end));
}

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;
}

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->result) {
    printf("Liveness check passed!\n");
    return 0;
  } else {
    printf("Liveness check failed!\n");
    return -1;
  }
}

// Use the qemu edu device to print the factorial of n to stdout.
// 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->output);

  return 0;
}

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);
}
