// 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/async-loop/default.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 <stdio.h>
#include <unistd.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>

#include <utility>

#include "src/lib/fxl/strings/string_printf.h"

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), {});
    zx_process_exit(0);
  }

  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);
  launch_info.arguments.emplace();
  while (argc) {
    launch_info.arguments->push_back(*argv);
    consume_arg(&argc, &argv);
  }

  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  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;
}
