// 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 <fidl/fuchsia.memorypressure/cpp/fidl.h>
#include <fidl/fuchsia.process.lifecycle/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/processargs.h>

#include "src/graphics/bin/vulkan_loader/app.h"
#include "src/graphics/bin/vulkan_loader/icd_runner.h"
#include "src/graphics/bin/vulkan_loader/loader.h"
#include "src/graphics/bin/vulkan_loader/magma_dependency_injection.h"
#include "src/graphics/bin/vulkan_loader/structured_config_lib.h"
#include "src/lib/fxl/command_line.h"
#include "src/lib/fxl/log_settings_command_line.h"

namespace {
zx::result<fidl::ClientEnd<fuchsia_memorypressure::Provider>> GetMemoryPressureProvider() {
  auto endpoints = fidl::CreateEndpoints<fuchsia_memorypressure::Provider>();
  if (endpoints.is_error()) {
    FX_LOGS(INFO) << "Failed to create endpoints: " << endpoints.status_string();
    return endpoints.take_error();
  }
  if (auto result = component::Connect(std::move(endpoints->server)); result.is_error()) {
    return result.take_error();
  }
  return zx::ok(std::move(endpoints->client));
}

class LifecycleHandler : public fidl::Server<fuchsia_process_lifecycle::Lifecycle> {
 public:
  static LifecycleHandler Create(async::Loop* loop) {
    fidl::ServerEnd server_end = fidl::ServerEnd<fuchsia_process_lifecycle::Lifecycle>{
        zx::channel(zx_take_startup_handle(PA_LIFECYCLE))};
    ZX_ASSERT_MSG(server_end.is_valid(), "Invalid handle for PA_LIFECYCLE!");
    return LifecycleHandler(loop, std::move(server_end));
  }

 private:
  explicit LifecycleHandler(async::Loop* loop,
                            fidl::ServerEnd<fuchsia_process_lifecycle::Lifecycle> server_end)
      : loop_(loop),
        binding_(loop->dispatcher(), std::move(server_end), this, fidl::kIgnoreBindingClosure) {}
  void Stop(StopCompleter::Sync& completer) override {
    loop_->Quit();
    binding_.Close(ZX_OK);
  }

  async::Loop* loop_;
  fidl::ServerBinding<fuchsia_process_lifecycle::Lifecycle> binding_;
};
}  // namespace

int main(int argc, const char* const* argv) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  async::Loop runner_loop(&kAsyncLoopConfigNoAttachToCurrentThread);

  LifecycleHandler lifecycle_handler = LifecycleHandler::Create(&loop);

  runner_loop.StartThread("IcdRunner");
  fxl::SetLogSettingsFromCommandLine(fxl::CommandLineFromArgcArgv(argc, argv));

  auto outgoing_dir = component::OutgoingDirectory(loop.dispatcher());
  auto structured_config = structured_config_lib::Config::TakeFromStartupHandle();

  LoaderApp app(&outgoing_dir, loop.dispatcher(), structured_config);
  zx_status_t status = app.InitDeviceWatcher();

  if (status != ZX_OK) {
    FX_LOGS(INFO) << "Failed to initialize device watcher " << status;
    return -1;
  }

  status = app.InitDebugFs();

  if (status != ZX_OK) {
    FX_LOGS(INFO) << "Failed to initialize debug fs " << status;
    return -1;
  }

  zx::result manager = MagmaDependencyInjection::Create(&GetMemoryPressureProvider);
  if (manager.is_error()) {
    FX_LOGS(INFO) << "Failed to initialize gpu manager " << manager.status_string();
    return -1;
  }

  auto component_runner = std::make_unique<IcdRunnerImpl>(runner_loop.dispatcher());
  if (auto status = IcdRunnerImpl::Add(std::move(component_runner), outgoing_dir);
      status.is_error()) {
    FX_LOGS(ERROR) << "Failed to add ICD runner: " << status.status_string();
    return -1;
  }

  if (auto result = LoaderImpl::Add(outgoing_dir, &app, loop.dispatcher()); result.is_error()) {
    FX_LOGS(ERROR) << "Failed to create loader service: " << result.status_string();
  }

  if (auto status = outgoing_dir.ServeFromStartupInfo(); status.is_error()) {
    FX_LOGS(ERROR) << "Failed to serve outgoing directory: " << status.status_string();
    return -1;
  }

  FX_LOGS(INFO) << "Vulkan loader initialized.";
  loop.Run();
  runner_loop.Shutdown();
  loop.Shutdown();
  return 0;
}
