// 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 <lib/cmdline/args_parser.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/zx/thread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <memory>
#include <thread>

#include "src/developer/debug/debug_agent/debug_agent.h"
#include "src/developer/debug/debug_agent/fidl_server.h"
#include "src/developer/debug/debug_agent/socket_connection.h"
#include "src/developer/debug/debug_agent/unwind.h"
#include "src/developer/debug/debug_agent/zircon_system_interface.h"
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/shared/platform_message_loop.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/lib/fxl/strings/string_printf.h"

using namespace debug_ipc;

namespace debug_agent {
namespace {

// Valid options for the --unwind flag.
const char kAospUnwinder[] = "aosp";
const char kNgUnwinder[] = "ng";
const char kFuchsiaUnwinder[] = "fuchsia";

struct CommandLineOptions {
  int port = 0;
  bool debug_mode = false;
  bool channel_mode = false;
  std::string unwind = kAospUnwinder;
};

const char kHelpIntro[] = R"(debug_agent --port=<port> [ <options> ]

  The debug_agent provides the on-device stub for the ZXDB frontend to talk
  to. Once you launch the debug_agent, connect zxdb to the same port you
  provide on the command-line.

Options

)";

const char kHelpHelp[] = R"(  --help
  -h
      Prints all command-line switches.)";

const char kPortHelp[] = R"(  --port=<port>
    [Required] TCP port number to listen to incoming connections on.)";

const char kDebugModeHelp[] = R"(  --debug-mode
  -d
      Run the agent on debug mode. This will enable conditional logging
      messages and timing profiling. Mainly useful for people developing zxdb.)";

const char kChannelModeHelp[] = R"(  --channel-mode
      Run the agent on in channel mode. The agent will listen for channels through the
      fuchsia.debugger.DebugAgent API. This is necessary for overnet.)";

const char kUnwindHelp[] = R"(  --unwind=[aosp|ng|fuchsia]
      Force using a specific unwinder for generating stack traces.)";

cmdline::Status ParseCommandLine(int argc, const char* argv[], CommandLineOptions* options) {
  cmdline::ArgsParser<CommandLineOptions> parser;

  parser.AddSwitch("port", 0, kPortHelp, &CommandLineOptions::port);
  parser.AddSwitch("debug-mode", 'd', kDebugModeHelp, &CommandLineOptions::debug_mode);
  parser.AddSwitch("channel-mode", 0, kChannelModeHelp, &CommandLineOptions::channel_mode);
  parser.AddSwitch("unwind", 0, kUnwindHelp, &CommandLineOptions::unwind);

  // Special --help switch which doesn't exist in the options structure.
  bool requested_help = false;
  parser.AddGeneralSwitch("help", 'h', kHelpHelp, [&requested_help]() { requested_help = true; });

  std::vector<std::string> params;
  cmdline::Status status = parser.Parse(argc, argv, options, &params);
  if (status.has_error())
    return status;

  // Handle --help switch since we're the one that knows about the switches.
  if (requested_help)
    return cmdline::Status::Error(kHelpIntro + parser.GetHelp());

  return cmdline::Status::Ok();
}

}  // namespace
}  // namespace debug_agent

// main --------------------------------------------------------------------------------------------

int main(int argc, const char* argv[]) {
  debug_agent::CommandLineOptions options;
  cmdline::Status status = ParseCommandLine(argc, argv, &options);
  if (status.has_error()) {
    fprintf(stderr, "%s\n", status.error_message().c_str());
    return 1;
  }

  // Decode the unwinder type.
  if (options.unwind == debug_agent::kAospUnwinder) {
    debug_agent::SetUnwinderType(debug_agent::UnwinderType::kAndroid);
  } else if (options.unwind == debug_agent::kNgUnwinder) {
    debug_agent::SetUnwinderType(debug_agent::UnwinderType::kNgUnwind);
  } else if (options.unwind == debug_agent::kFuchsiaUnwinder) {
    debug_agent::SetUnwinderType(debug_agent::UnwinderType::kFuchsia);
  } else {
    fprintf(stderr, "Invalid option for --unwind. See debug_agent --help.\n");
    return 1;
  }

  debug_ipc::SetLogCategories({LogCategory::kAll});
  if (options.debug_mode) {
    printf("Running the debug agent in debug mode.\n");
    debug_ipc::SetDebugMode(true);
  }

  if (options.channel_mode || options.port) {
    auto services = sys::ServiceDirectory::CreateFromNamespace();

    zx::channel exception_channel;
    auto message_loop = std::make_unique<PlatformMessageLoop>();
    std::string init_error_message;
    if (!message_loop->Init(&init_error_message)) {
      FX_LOGS(ERROR) << init_error_message;
      return 1;
    }

    // The scope ensures the objects are destroyed before calling Cleanup on the MessageLoop.
    {
      // The debug agent is independent of whether it's connected or not.
      // DebugAgent::Disconnect is called by ~SocketConnection is called by ~SocketServer, so the
      // debug agent must be destructed after the SocketServer.
      debug_agent::DebugAgent debug_agent(std::make_unique<debug_agent::ZirconSystemInterface>());

      debug_agent::SocketServer server;
      if (!server.Init(options.port)) {
        message_loop->Cleanup();
        return 1;
      }

      // The following loop will attempt to patch a stream to the debug agent in order to enable
      // communication.
      while (true) {
        if (options.channel_mode) {
          // Connect to FIDL service which will wait for an incoming connection from a client.
          // This happens within the message_loop so it does not need a new thread.
          debug_agent::DebugAgentImpl fidl_agent(&debug_agent);
          fidl::BindingSet<fuchsia::debugger::DebugAgent> bindings;
          auto context = sys::ComponentContext::CreateAndServeOutgoingDirectory();
          context->outgoing()->AddPublicService(bindings.GetHandler(&fidl_agent));

          message_loop->Run();

          DEBUG_LOG(Agent) << "Joining connection thread.";
        } else {
          // Start a new thread that will listen on a socket from an incoming connection from a
          // client. In the meantime, the main thread will block waiting for something to be posted
          // to the main thread.
          //
          // When the connection thread effectively receives a connection, it will post a task to
          // the loop to create the agent and begin normal debugger operation. Once the application
          // quits the loop, the code will clean the connection thread and create another or exit
          // the loop, according to the current agent's configuration.
          debug_agent::SocketServer::ConnectionConfig conn_config;
          conn_config.message_loop = message_loop.get();
          conn_config.debug_agent = &debug_agent;
          conn_config.port = options.port;
          std::thread conn_thread(&debug_agent::SocketServer::Run, &server, std::move(conn_config));

          message_loop->Run();

          DEBUG_LOG(Agent) << "Joining connection thread.";
          conn_thread.join();
        }

        // See if the debug agent was told to exit.
        if (debug_agent.should_quit())
          break;

        // Prepare for another connection.
        // The resources need to be freed on the message loop's thread.
        server.Reset();
      }
    }
    message_loop->Cleanup();
  } else {
    fprintf(stderr, "ERROR: --port=<port-number> required. See debug_agent --help.\n\n");
    return 1;
  }

  // It's very useful to have a simple message that informs the debug agent
  // exited successfully.
  fprintf(stderr, "\rSee you, Space Cowboy...\r\n");
  return 0;
}
