// Copyright 2017 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 <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/sys/index/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/limits.h>
#include <lib/sys/cpp/file_descriptor.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/sys/cpp/termination_reason.h>
#include <src/lib/fxl/strings/string_printf.h>
#include <stdio.h>
#include <unistd.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <utility>

using fuchsia::sys::TerminationReason;
using fuchsia::sys::index::ComponentIndex_FuzzySearch_Response;
using fuchsia::sys::index::ComponentIndex_FuzzySearch_Result;
using fuchsia::sys::index::ComponentIndexPtr;
using fxl::StringPrintf;

static void consume_arg(int* argc, const char*** argv) {
  --(*argc);
  ++(*argv);
}

void launch(fuchsia::sys::LauncherSyncPtr launcher,
            fuchsia::sys::ComponentControllerPtr controller,
            fuchsia::sys::LaunchInfo launch_info, async::Loop* loop,
            bool daemonize) {
  if (daemonize) {
    launcher->CreateComponent(std::move(launch_info), {});
    return;
  }

  std::string url = launch_info.url;
  launcher->CreateComponent(std::move(launch_info), controller.NewRequest());

  controller.events().OnTerminated = [&url](
                                         int64_t return_code,
                                         TerminationReason termination_reason) {
    if (termination_reason != TerminationReason::EXITED) {
      fprintf(stderr, "%s: %s\n", url.c_str(),
              sys::HumanReadableTerminationReason(termination_reason).c_str());
    }
    zx_process_exit(return_code);
  };
  loop->Run();
}

int main(int argc, const char** argv) {
  if (argc < 2) {
    fprintf(stderr, "Usage: run [-d] <program> <args>*\n");
    return 1;
  }

  // argv[0] is the program name;
  consume_arg(&argc, &argv);

  bool daemonize = false;
  if (std::string(argv[0]) == "-d") {
    daemonize = true;
    consume_arg(&argc, &argv);
  }

  // Perform a fuzzy search on the program name if it is not in URI format.
  bool fuzzy_search = false;
  if (std::string(argv[0]).find("://") == std::string::npos) {
    fuzzy_search = true;
  }

  std::string program_name = argv[0];
  consume_arg(&argc, &argv);

  fuchsia::sys::LaunchInfo launch_info;
  launch_info.url = program_name;
  launch_info.out = sys::CloneFileDescriptor(STDOUT_FILENO);
  launch_info.err = sys::CloneFileDescriptor(STDERR_FILENO);
  while (argc) {
    launch_info.arguments.push_back(*argv);
    consume_arg(&argc, &argv);
  }

  async::Loop loop(&kAsyncLoopConfigAttachToThread);
  auto services = sys::ServiceDirectory::CreateFromNamespace();

  // Connect to the Launcher service through our static environment.
  fuchsia::sys::LauncherSyncPtr launcher;
  services->Connect(launcher.NewRequest());
  fuchsia::sys::ComponentControllerPtr controller;

  if (fuzzy_search) {
    fidl::InterfaceHandle<fuchsia::io::Directory> directory;
    fuchsia::sys::LaunchInfo index_launch_info;
    index_launch_info.url =
        "fuchsia-pkg://fuchsia.com/component_index#meta/component_index.cmx";
    index_launch_info.directory_request = directory.NewRequest().TakeChannel();
    launcher->CreateComponent(std::move(index_launch_info),
                              controller.NewRequest());

    ComponentIndexPtr index;
    sys::ServiceDirectory index_provider(std::move(directory));
    index_provider.Connect(index.NewRequest());
    index.set_error_handler([&program_name](zx_status_t status) {
      fprintf(
          stderr,
          "Error: \"%s\" is not a valid URL. Attempted to match to a URL with "
          "fuchsia.sys.index.FuzzySearch, but the service is not available\n",
          program_name.c_str());
      zx_process_exit(1);
    });

    index->FuzzySearch(
        program_name,
        [&launcher, &controller, &launch_info, &loop, &program_name,
         &daemonize](ComponentIndex_FuzzySearch_Result result) {
          if (result.is_err()) {
            fprintf(stderr,
                    "Error: \"%s\" contains unsupported characters for fuzzy "
                    "matching. Valid characters are [A-Z a-z 0-9 / _ - .].\n",
                    program_name.c_str());
            zx_process_exit(1);
          } else {
            ComponentIndex_FuzzySearch_Response response = result.response();
            std::vector<std::string> uris = response.uris;
            if (uris.size() == 0) {
              fprintf(stderr, "Error: \"%s\" did not match any components.\n",
                      program_name.c_str());
              zx_process_exit(1);
            } else if (uris.size() != 1) {
              for (auto& uri : uris) {
                fprintf(stderr, "%s\n", uri.c_str());
              }
              fprintf(stderr, "Error: \"%s\" matched multiple components.\n",
                      program_name.c_str());
              zx_process_exit(1);
            } else {
              std::string matched_name = uris[0];
              fprintf(stdout, "Found %s, executing.\n", matched_name.c_str());
              launch_info.url = matched_name;
              launch(std::move(launcher), std::move(controller),
                     std::move(launch_info), &loop, daemonize);
            }
          }
        });
    loop.Run();
  } else {
    launch(std::move(launcher), std::move(controller), std::move(launch_info),
           &loop, daemonize);
  }

  return 0;
}
