// 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 "src/developer/debug/zxdb/console/commands/verb_connect.h"

#include <map>
#include <string>

#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/common/inet_util.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/console.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/verbs.h"

namespace zxdb {

namespace {

constexpr int kUnixSwitch = 1;
constexpr int kQuietSwitch = 2;

const char kConnectShortHelp[] = "connect: Connect to a remote system for debugging.";
const char kConnectUsage[] = "connect [ <remote_address> ]";
const char kConnectHelp[] = R"(
  Connects to a debug_agent at the given address/port. With no arguments,
  attempts to reconnect to the previously used remote address.

  See also "disconnect".

Addresses

  Addresses can be of the form "<host> <port>" or "<host>:<port>". When using
  the latter form, IPv6 addresses must be [bracketed]. Otherwise the brackets
  are optional.

Options

  --unix-socket
  -u
      Attempt to connect to a unix socket. In this case <host> is a filesystem
      path.

  --quiet
  -q
      Produce less information console output.

Examples

  connect mystem.localnetwork 1234
  connect mystem.localnetwork:1234
  connect 192.168.0.4:1234
  connect 192.168.0.4 1234
  connect [1234:5678::9abc] 1234
  connect 1234:5678::9abc 1234
  connect [1234:5678::9abc]:1234
  connect -u /path/to/socket
)";

// Displays the failed connection error message. Connections are normally initiated on startup
// and it can be difficult to see the message with all the other normal startup messages. This
// can confuse users who wonder why nothing is working. As a result, make the message really big.
void DisplayConnectionFailed(CommandContext* cmd_context, const Err& err) {
  if (cmd_context->GetConsoleContext()->session()->IsConnected()) {
    // There could be a race connection (like the user hit enter twice rapidly when issuing the
    // connection command) that will cause a connection to fail because there's already one pending.
    // This might not have been knowable before issuing the command. If there's already a
    // connection, skip the big scary message.
    cmd_context->ReportError(err);
  } else {
    // Print a banner to highlight the error.
    OutputBuffer out;
    out.Append(Syntax::kError, "╒═══════════════════════════════════════════╕\n│ ");
    out.Append(Syntax::kHeading, "Connection to the debugged system failed. ");
    out.Append(Syntax::kError, "│\n╘═══════════════════════════════════════════╛\n");
    cmd_context->Output(out);
    cmd_context->ReportError(err);
  }
}

void RunVerbConnect(const Command& cmd, fxl::RefPtr<CommandContext> cmd_context) {
  SessionConnectionInfo connection_info;

  // Should always be present because we were called synchronously.
  ConsoleContext* console_context = cmd_context->GetConsoleContext();

  // Catch the "already connected" case early to display a simple low-key error message. This
  // avoids the more complex error messages issues by the Session object which might seem
  // out-of-context.
  if (console_context->session()->IsConnected()) {
    return cmd_context->ReportError(
        Err("connect: Already connected to the debugged system. Type \"status\" for more."));
  }

  const bool quiet = cmd.HasSwitch(kQuietSwitch);

  if (cmd.HasSwitch(kUnixSwitch)) {
    connection_info.type = SessionConnectionType::kUnix;
    if (cmd.args().size() == 1) {
      connection_info.host = cmd.args()[0];
    } else {
      return cmd_context->ReportError(Err(ErrType::kInput, "Too many arguments."));
    }
  } else {
    // 0 args means pass empty string and 0 port to try to reconnect.
    if (cmd.args().size() == 1) {
      const std::string& host_port = cmd.args()[0];
      // Provide an additional assist to users if they forget to wrap an IPv6 address in [].
      if (Ipv6HostPortIsMissingBrackets(host_port)) {
        return cmd_context->ReportError(Err(ErrType::kInput,
                                            "For IPv6 addresses use either: \"[::1]:1234\"\n"
                                            "or the two-parameter form: \"::1 1234."));
      }
      Err err = ParseHostPort(host_port, &connection_info.host, &connection_info.port);
      if (err.has_error())
        return cmd_context->ReportError(err);
      connection_info.type = SessionConnectionType::kNetwork;
    } else if (cmd.args().size() == 2) {
      Err err =
          ParseHostPort(cmd.args()[0], cmd.args()[1], &connection_info.host, &connection_info.port);
      if (err.has_error())
        return cmd_context->ReportError(err);
      connection_info.type = SessionConnectionType::kNetwork;
    } else if (cmd.args().size() > 2) {
      return cmd_context->ReportError(Err(ErrType::kInput, "Too many arguments."));
    }
  }

  console_context->session()->Connect(connection_info,
                                      [cmd_context, quiet](const Err& err) mutable {
                                        if (err.has_error()) {
                                          // Don't display error message if they canceled the
                                          // connection.
                                          if (err.type() != ErrType::kCanceled)
                                            DisplayConnectionFailed(cmd_context.get(), err);
                                        } else {
                                          if (!quiet)
                                            cmd_context->Output("Connected successfully.\n");
                                        }
                                      });
  if (!quiet)
    cmd_context->Output("Connecting (use \"disconnect\" to cancel)...\n");
}

}  // namespace

VerbRecord GetConnectVerbRecord() {
  SwitchRecord unix_switch(kUnixSwitch, false, "unix-socket", 'u');
  SwitchRecord quiet_switch(kQuietSwitch, false, "quiet", 'q');
  VerbRecord connect_record = VerbRecord(&RunVerbConnect, {"connect"}, kConnectShortHelp,
                                         kConnectUsage, kConnectHelp, CommandGroup::kGeneral);
  connect_record.switches.push_back(unix_switch);
  connect_record.switches.push_back(quiet_switch);
  connect_record.needs_elision = true;
  return connect_record;
}

}  // namespace zxdb
