// 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 <fcntl.h>
#include <fidl/fuchsia.device/cpp/wire.h>
#include <fidl/fuchsia.hardware.block.partition/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/watcher.h>

#include <memory>

#include <fbl/unique_fd.h>

#include "src/lib/uuid/uuid.h"

void usage() {
  fprintf(stderr,
          "usage: waitfor <expr>+        wait for devices to be published\n"
          "\n"
          "expr:  class=<name>           device class <name>   (required)\n"
          "\n"
          "       topo=<path>            topological path contains <path>\n"
          "       part.guid=<guid>       block device GUID matches <guid>\n"
          "       part.type.guid=<guid>  partition type GUID matches <guid>\n"
          "       part.name=<name>       partition name matches <name>\n"
          "\n"
          "       timeout=<msec>         fail if no match after <msec> milliseconds\n"
          "       print                  write name of matching devices to stdout\n"
          "       forever                don't stop after the first match\n"
          "                              also don't fail on timeout after first match\n"
          "       verbose                print debug chatter to stderr\n"
          "\n"
          "example: waitfor class=block part.name=system print\n");
}

struct App;

class Rule {
 public:
  using Func = zx_status_t (*)(const App& app, const char* arg,
                               fidl::UnownedClientEnd<fuchsia_io::Directory> dir, const char* name);

  Rule(const char* arg, Func func) : func_(func), arg_(arg) {}

  zx_status_t Call(const App& app, fidl::UnownedClientEnd<fuchsia_io::Directory> dir,
                   const char* name) const {
    return func_(app, arg_, dir, name);
  }

 private:
  Func func_;
  const char* arg_;
};

struct App {
  bool matched;

  const bool verbose;
  const bool print;
  const bool forever;
  const char* devclass;
  const std::vector<Rule> rules;
};

zx_status_t watchcb(int dirfd, int event, const char* fn, void* cookie) {
  if (std::string_view{fn} == ".") {
    return ZX_OK;
  }
  if (event != WATCH_EVENT_ADD_FILE) {
    return ZX_OK;
  }
  App& app = *static_cast<App*>(cookie);
  if (app.verbose) {
    fprintf(stderr, "waitfor: device='/dev/class/%s/%s'\n", app.devclass, fn);
  }
  const fdio_cpp::UnownedFdioCaller caller(dirfd);
  for (const Rule& r : app.rules) {
    switch (const zx_status_t status = r.Call(app, caller.directory(), fn); status) {
      case ZX_OK:
        // rule matched
        continue;
      case ZX_ERR_NEXT:
        // rule did not match
        return ZX_OK;
      default:
        // fatal error
        return status;
    }
  }

  app.matched = true;

  if (app.print) {
    printf("/dev/class/%s/%s\n", app.devclass, fn);
  }

  if (app.forever) {
    return ZX_OK;
  }
  return ZX_ERR_STOP;
}

// Expression evaluators return OK on match, NEXT on no-match
// any other error is fatal

zx_status_t expr_topo(const App& app, const char* arg,
                      fidl::UnownedClientEnd<fuchsia_io::Directory> dir, const char* name) {
  std::string controller_path = std::string(name) + "/device_controller";
  zx::result controller =
      component::ConnectAt<fuchsia_device::Controller>(dir, controller_path.c_str());
  if (controller.is_error()) {
    fprintf(stderr, "waitfor: warning: failed to open: '%s' :%s \n", name,
            controller.status_string());
    return controller.error_value();
  }
  const fidl::WireResult result = fidl::WireCall(controller.value())->GetTopologicalPath();
  if (!result.ok()) {
    fprintf(stderr, "waitfor: warning: cannot request topological path: '%s': %s\n",
            controller_path.c_str(), result.FormatDescription().c_str());
    return result.status();
  }
  const auto* res = result.Unwrap();
  if (res->is_error()) {
    const zx_status_t status = res->error_value();
    fprintf(stderr, "waitfor: warning: failed to get topological path: %s\n",
            zx_status_get_string(status));
    return status;
  }
  const std::string_view got = res->value()->path.get();
  const std::string_view expected(arg);
  if (app.verbose) {
    fprintf(stderr, "waitfor: topological path='%s'\n", std::string(got).c_str());
  }
  // Check if the topo path contains our needle.
  if (got.find(expected) != std::string::npos) {
    return ZX_OK;
  }
  return ZX_ERR_NEXT;
}

zx_status_t expr_part_guid(const App& app, const char* arg,
                           fidl::UnownedClientEnd<fuchsia_io::Directory> dir, const char* name) {
  zx::result partition =
      component::ConnectAt<fuchsia_hardware_block_partition::Partition>(dir, name);
  if (partition.is_error()) {
    fprintf(stderr, "waitfor: warning: failed to open: '%s :%s \n", name,
            partition.status_string());
    return partition.error_value();
  }

  const fidl::WireResult result = fidl::WireCall(partition.value())->GetInstanceGuid();
  if (!result.ok()) {
    fprintf(stderr, "waitfor: warning: cannot request instance guid: %s\n",
            result.FormatDescription().c_str());
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (const zx_status_t status = response.status; status != ZX_OK) {
    fprintf(stderr, "waitfor: warning: cannot get instance guid: %s\n",
            zx_status_get_string(status));
    return result.status();
  }
  fidl::Array value = response.guid->value;
  static_assert(decltype(value)::size() == uuid::kUuidSize);
  const std::string text = uuid::Uuid(value.data()).ToString();
  if (app.verbose) {
    fprintf(stderr, "waitfor: part.guid='%s'\n", text.c_str());
  }
  if (strcasecmp(text.c_str(), arg) == 0) {
    return ZX_OK;
  }
  return ZX_ERR_NEXT;
}

zx_status_t expr_part_type_guid(const App& app, const char* arg,
                                fidl::UnownedClientEnd<fuchsia_io::Directory> dir,
                                const char* name) {
  zx::result partition =
      component::ConnectAt<fuchsia_hardware_block_partition::Partition>(dir, name);
  if (partition.is_error()) {
    fprintf(stderr, "waitfor: warning: failed to open: '%s' :%s \n", name,
            partition.status_string());
    return partition.error_value();
  }

  const fidl::WireResult result = fidl::WireCall(partition.value())->GetTypeGuid();
  if (!result.ok()) {
    fprintf(stderr, "waitfor: warning: cannot request type guid: %s\n",
            result.FormatDescription().c_str());
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (const zx_status_t status = response.status; status != ZX_OK) {
    fprintf(stderr, "waitfor: warning: cannot get type guid: %s\n", zx_status_get_string(status));
    return result.status();
  }
  fidl::Array value = response.guid->value;
  static_assert(decltype(value)::size() == uuid::kUuidSize);
  const std::string text = uuid::Uuid(value.data()).ToString();
  if (app.verbose) {
    fprintf(stderr, "waitfor: part.type.guid='%s'\n", text.c_str());
  }
  if (strcasecmp(text.c_str(), arg) == 0) {
    return ZX_OK;
  }
  return ZX_ERR_NEXT;
}

zx_status_t expr_part_name(const App& app, const char* arg,
                           fidl::UnownedClientEnd<fuchsia_io::Directory> dir, const char* name) {
  zx::result partition =
      component::ConnectAt<fuchsia_hardware_block_partition::Partition>(dir, name);
  if (partition.is_error()) {
    fprintf(stderr, "waitfor: warning: failed to open: '%s' :%s \n", name,
            partition.status_string());
    return partition.error_value();
  }

  const fidl::WireResult result = fidl::WireCall(partition.value())->GetName();
  if (!result.ok()) {
    fprintf(stderr, "waitfor: warning: cannot request partition name: %s\n",
            result.FormatDescription().c_str());
    return result.status();
  }
  const fidl::WireResponse response = result.value();
  if (const zx_status_t status = response.status; status != ZX_OK) {
    fprintf(stderr, "waitfor: warning: cannot get type guid: %s\n", zx_status_get_string(status));
    return result.status();
  }
  const std::string partition_name(response.name.get());
  if (app.verbose) {
    fprintf(stderr, "waitfor: part.name='%s'\n", partition_name.c_str());
  }
  if (strcmp(arg, partition_name.c_str()) == 0) {
    return ZX_OK;
  }
  return ZX_ERR_NEXT;
}

int main(int argc, char** argv) {
  if (argc == 1) {
    usage();
    exit(1);
  }

  bool print = false;
  bool verbose = false;
  bool forever = false;
  zx_duration_t timeout = 0;
  const char* devclass = nullptr;
  std::vector<Rule> rules;
  while (argc > 1) {
    if (!strcmp(argv[1], "print")) {
      print = true;
    } else if (!strcmp(argv[1], "verbose")) {
      verbose = true;
    } else if (!strcmp(argv[1], "forever")) {
      forever = true;
    } else if (!strncmp(argv[1], "timeout=", 8)) {
      timeout = ZX_MSEC(atoi(argv[1] + 8));
      if (timeout == 0) {
        fprintf(stderr, "waitfor: error: timeout of 0 not allowed\n");
        exit(1);
      }
    } else if (!strncmp(argv[1], "class=", 6)) {
      devclass = argv[1] + 6;
    } else if (!strncmp(argv[1], "topo=", 5)) {
      rules.emplace_back(argv[1] + 5, expr_topo);
    } else if (!strncmp(argv[1], "part.guid=", 10)) {
      rules.emplace_back(argv[1] + 10, expr_part_guid);
    } else if (!strncmp(argv[1], "part.type.guid=", 15)) {
      rules.emplace_back(argv[1] + 15, expr_part_guid);
    } else if (!strncmp(argv[1], "part.name=", 10)) {
      rules.emplace_back(argv[1] + 10, expr_part_name);
    } else {
      fprintf(stderr, "waitfor: error: unknown expr '%s'\n\n", argv[1]);
      usage();
      exit(1);
    }
    argc--;
    argv++;
  }

  if (devclass == nullptr) {
    fprintf(stderr, "waitfor: error: no class specified\n");
    exit(1);
  }

  if (rules.empty()) {
    fprintf(stderr, "waitfor: error: no match expressions specified\n");
    exit(1);
  }

  const std::string path = std::string("/dev/class/") + devclass;

  const fbl::unique_fd dirfd(open(path.c_str(), O_DIRECTORY | O_RDONLY));
  if (!dirfd.is_valid()) {
    fprintf(stderr, "waitfor: error: cannot watch class '%s': %s\n", devclass, strerror(errno));
    exit(1);
  }

  zx_time_t deadline;
  if (timeout == 0) {
    deadline = ZX_TIME_INFINITE;
  } else {
    deadline = zx_deadline_after(timeout);
  }

  App app = {
      .verbose = verbose,
      .print = print,
      .forever = forever,
      .devclass = devclass,
      .rules = std::move(rules),
  };
  switch (const zx_status_t status = fdio_watch_directory(dirfd.get(), watchcb, deadline, &app);
          status) {
    case ZX_ERR_STOP:
      // clean exit on a match
      return 0;
    case ZX_ERR_TIMED_OUT:
      // timeout, but if we're in forever mode and matched any, its good
      if (app.matched && app.forever) {
        return 0;
      }
      break;
    default:
      // any other situation? failure
      return 1;
  }
}
