// 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;

const char kConnectShortHelp[] = R"(connect: Connect to a remote system for debugging.)";
const char kConnectHelp[] =
    R"(connect [ <remote_address> ]

  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.

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(const Err& err) {
  OutputBuffer out;
  if (Console::get()->context().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.
    out.Append(err);
  } else {
    out.Append(Syntax::kError, "╒═══════════════════════════════════════════╕\n│ ");
    out.Append(Syntax::kHeading, "Connection to the debugged system failed. ");
    out.Append(Syntax::kError, "│\n╘═══════════════════════════════════════════╛\n");
    out.Append(err);
    out.Append(Syntax::kError, "\n\nThe debugger will not be usable without connecting.\n\n");
  }
  Console::get()->Output(out);
}

Err RunVerbConnect(ConsoleContext* context, const Command& cmd,
                   CommandCallback callback = nullptr) {
  SessionConnectionInfo connection_info;

  // 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 (context->session()->IsConnected())
    return Err("connect: Already connected to the debugged system. Type \"status\" for more.");

  if (cmd.HasSwitch(kUnixSwitch)) {
    connection_info.type = SessionConnectionType::kUnix;
    if (cmd.args().size() == 1) {
      connection_info.host = cmd.args()[0];
    } else {
      return 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 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 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 err;
      connection_info.type = SessionConnectionType::kNetwork;
    } else if (cmd.args().size() > 2) {
      return Err(ErrType::kInput, "Too many arguments.");
    }
  }

  context->session()->Connect(
      connection_info, [callback = std::move(callback), cmd](const Err& err) mutable {
        if (err.has_error()) {
          // Don't display error message if they canceled the connection.
          if (err.type() != ErrType::kCanceled)
            DisplayConnectionFailed(err);
        } else {
          OutputBuffer msg;
          msg.Append("Connected successfully.\n");

          // Assume if there's a callback this is not being run interactively. Otherwise, show the
          // usage tip.
          if (!callback) {
            msg.Append(Syntax::kWarning, "👉 ");
            msg.Append(Syntax::kComment,
                       "Normally you will \"run <program path>\" or \"attach "
                       "<process koid>\".");
          }
          Console::get()->Output(msg);
        }

        if (callback)
          callback(err);
      });
  Console::get()->Output("Connecting (use \"disconnect\" to cancel)...\n");

  return Err();
}

}  // namespace

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

}  // namespace zxdb
