// Copyright 2019 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.kernel/cpp/wire.h>
#include <fidl/fuchsia.logger/cpp/wire.h>
#include <lib/fs-pty/service.h>
#include <lib/service/llcpp/service.h>
#include <lib/svc/outgoing.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include <fbl/string_printf.h>

#include "src/bringup/bin/console/args.h"
#include "src/bringup/bin/console/console.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"

namespace {

zx::resource GetDebugResource() {
  auto client_end = service::Connect<fuchsia_kernel::DebugResource>();
  if (client_end.is_error()) {
    printf("console: Could not connect to DebugResource service: %s\n", client_end.status_string());
    return {};
  }

  auto client = fidl::BindSyncClient(std::move(client_end.value()));
  auto result = client->Get();
  if (result.status() != ZX_OK) {
    printf("console: Could not retrieve DebugResource: %s\n",
           zx_status_get_string(result.status()));
    return {};
  }
  return std::move(result->resource);
}

zx_status_t ConnectListener(fidl::ClientEnd<fuchsia_logger::LogListenerSafe> listener,
                            std::vector<std::string> allowed_log_tags) {
  auto client_end = service::Connect<fuchsia_logger::Log>();
  if (client_end.is_error()) {
    printf("console: fdio_service_connect() = %s\n", client_end.status_string());
    return client_end.status_value();
  }

  auto log = fidl::BindSyncClient(std::move(client_end.value()));
  std::vector<fidl::StringView> tags;
  for (auto& tag : allowed_log_tags) {
    tags.emplace_back(fidl::StringView::FromExternal(tag));
  }
  fuchsia_logger::wire::LogFilterOptions options{
      .filter_by_pid = false,
      .filter_by_tid = false,
      .min_severity = fuchsia_logger::wire::LogLevelFilter::kTrace,
      .tags = fidl::VectorView<fidl::StringView>::FromExternal(tags),
  };
  auto result = log->ListenSafe(
      std::move(listener),
      fidl::ObjectView<fuchsia_logger::wire::LogFilterOptions>::FromExternal(&options));
  if (!result.ok()) {
    printf("console: fuchsia.logger.Log/ListenSafe() = %s\n", result.FormatDescription().c_str());
    return result.status();
  }
  return ZX_OK;
}

}  // namespace

int main(int argc, const char** argv) {
  zx_status_t status = StdoutToDebuglog::Init();
  if (status != ZX_OK) {
    return status;
  }

  zx::status boot_args = service::Connect<fuchsia_boot::Arguments>();
  if (boot_args.is_error()) {
    return boot_args.status_value();
  }
  const auto boot_args_client = fidl::BindSyncClient(*std::move(boot_args));

  Options opts;
  status = ParseArgs(console_config::Config::from_args(), boot_args_client, &opts);
  if (status != ZX_OK) {
    return status;
  }

  async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);

  // Provide a RxSource that grabs the data from the kernel serial connection
  Console::RxSource rx_source = [debug_resource = GetDebugResource()](uint8_t* byte) {
    size_t length = 0;
    zx_status_t status =
        zx_debug_read(debug_resource.get(), reinterpret_cast<char*>(byte), sizeof(*byte), &length);
    if (status == ZX_ERR_NOT_SUPPORTED) {
      // Suppress the error print in this case.  No console on this machine.
      return status;
    } else if (status != ZX_OK) {
      printf("console: error %s, length %zu from zx_debug_read syscall, exiting.\n",
             zx_status_get_string(status), length);
      return status;
    }
    if (length != 1) {
      return ZX_ERR_SHOULD_WAIT;
    }
    return ZX_OK;
  };
  Console::TxSink tx_sink = [](const uint8_t* buffer, size_t length) {
    return zx_debug_write(reinterpret_cast<const char*>(buffer), length);
  };
  fbl::RefPtr<Console> console;
  status = Console::Create(std::move(rx_source), std::move(tx_sink),
                           std::move(opts.denied_log_tags), &console);
  if (status != ZX_OK) {
    printf("console: Console::Create() = %s\n", zx_status_get_string(status));
    return status;
  }

  auto endpoints = fidl::CreateEndpoints<fuchsia_logger::LogListenerSafe>();
  if (endpoints.is_error()) {
    return endpoints.status_value();
  }

  status = ConnectListener(std::move(endpoints->client), std::move(opts.allowed_log_tags));
  if (status != ZX_OK) {
    return status;
  }

  fidl::BindServer(loop.dispatcher(), std::move(endpoints->server), console.get());

  svc::Outgoing outgoing(loop.dispatcher());
  status = outgoing.ServeFromStartupInfo();
  if (status != ZX_OK) {
    printf("console: outgoing.ServeFromStartupInfo() = %s\n", zx_status_get_string(status));
    return status;
  }

  using Vnode =
      fs_pty::TtyService<fs_pty::SimpleConsoleOps<fbl::RefPtr<Console>>, fbl::RefPtr<Console>>;
  outgoing.svc_dir()->AddEntry(fidl::DiscoverableProtocolName<fuchsia_hardware_pty::Device>,
                               fbl::AdoptRef(new Vnode(std::move(console))));

  status = loop.Run();
  ZX_ASSERT(status == ZX_OK);
  return status;
}
