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

#include <inttypes.h>
#include <stdio.h>

#include <limits>

#include "src/developer/debug/zxdb/client/breakpoint.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/job.h"
#include "src/developer/debug/zxdb/client/job_context.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/console/command.h"
#include "src/developer/debug/zxdb/console/console_context.h"
#include "src/developer/debug/zxdb/console/format_function.h"
#include "src/developer/debug/zxdb/console/format_target.h"
#include "src/developer/debug/zxdb/console/output_buffer.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/expr/eval_context_impl.h"
#include "src/developer/debug/zxdb/expr/expr.h"
#include "src/developer/debug/zxdb/expr/expr_parser.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/number_parser.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/identifier.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/developer/debug/zxdb/symbols/symbol_utils.h"
#include "src/developer/debug/zxdb/symbols/target_symbols.h"
#include "src/developer/debug/zxdb/symbols/variable.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/strings/trim.h"

namespace zxdb {

Err AssertRunningTarget(ConsoleContext* context, const char* command_name, Target* target) {
  Target::State state = target->GetState();
  if (state == Target::State::kRunning)
    return Err();
  return Err(ErrType::kInput,
             fxl::StringPrintf("%s requires a running process but process %d is %s.", command_name,
                               context->IdForTarget(target), TargetStateToString(state)));
}

Err AssertStoppedThreadCommand(ConsoleContext* context, const Command& cmd, bool validate_nouns,
                               const char* command_name) {
  Err err;
  if (validate_nouns) {
    err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread});
    if (err.has_error())
      return err;
  }

  if (!cmd.thread()) {
    return Err("\"%s\" requires a thread but there is no current thread.", command_name);
  }
  if (cmd.thread()->GetState() != debug_ipc::ThreadRecord::State::kBlocked &&
      cmd.thread()->GetState() != debug_ipc::ThreadRecord::State::kCoreDump &&
      cmd.thread()->GetState() != debug_ipc::ThreadRecord::State::kSuspended) {
    return Err(
        "\"%s\" requires a suspended thread but thread %d is %s.\n"
        "To view and sync thread state with the remote system, type "
        "\"thread\".",
        command_name, context->IdForThread(cmd.thread()),
        ThreadStateToString(cmd.thread()->GetState(), cmd.thread()->GetBlockedReason()).c_str());
  }
  return Err();
}

Err AssertStoppedThreadWithFrameCommand(ConsoleContext* context, const Command& cmd,
                                        const char* command_name) {
  // Does most validation except noun checking.
  Err err = AssertStoppedThreadCommand(context, cmd, false, command_name);
  if (err.has_error())
    return err;

  // Stopped threads should always have a frame.
  FXL_DCHECK(cmd.frame());

  return cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
}

size_t CheckHexPrefix(const std::string& s) {
  if (s.size() >= 2u && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
    return 2u;
  return 0u;
}

Err StringToInt(const std::string& s, int* out) {
  int64_t value64;
  Err err = StringToInt64(s, &value64);
  if (err.has_error())
    return err;

  // Range check it can be stored in an int.
  if (value64 < static_cast<int64_t>(std::numeric_limits<int>::min()) ||
      value64 > static_cast<int64_t>(std::numeric_limits<int>::max()))
    return Err("This value is too large for an integer.");

  *out = static_cast<int>(value64);
  return Err();
}

Err StringToInt64(const std::string& s, int64_t* out) {
  *out = 0;

  // StringToNumber expects pre-trimmed input.
  std::string trimmed = fxl::TrimString(s, " ").ToString();

  ExprValue number_value;
  Err err = StringToNumber(trimmed, &number_value);
  if (err.has_error())
    return err;

  // Be careful to read the number out in its original sign-edness.
  if (number_value.GetBaseType() == BaseType::kBaseTypeUnsigned) {
    uint64_t u64;
    err = number_value.PromoteTo64(&u64);
    if (err.has_error())
      return err;

    // Range-check that the unsigned value can be put in a signed.
    if (u64 > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()))
      return Err("This value is too large.");
    *out = static_cast<int64_t>(u64);
    return Err();
  }

  // Expect everything else to be a signed number.
  if (number_value.GetBaseType() != BaseType::kBaseTypeSigned)
    return Err("This value is not the correct type.");
  return number_value.PromoteTo64(out);
}

Err StringToUint32(const std::string& s, uint32_t* out) {
  // Re-uses StringToUint64's and just size-checks the output.
  uint64_t value64;
  Err err = StringToUint64(s, &value64);
  if (err.has_error())
    return err;

  if (value64 > static_cast<uint64_t>(std::numeric_limits<uint32_t>::max())) {
    return Err("Expected 32-bit unsigned value, but %s is too large.", s.c_str());
  }
  *out = static_cast<uint32_t>(value64);
  return Err();
}

Err StringToUint64(const std::string& s, uint64_t* out) {
  *out = 0;

  // StringToNumber expects pre-trimmed input.
  std::string trimmed = fxl::TrimString(s, " ").ToString();

  ExprValue number_value;
  Err err = StringToNumber(trimmed, &number_value);
  if (err.has_error())
    return err;

  // Be careful to read the number out in its original sign-edness.
  if (number_value.GetBaseType() == BaseType::kBaseTypeSigned) {
    int64_t s64;
    err = number_value.PromoteTo64(&s64);
    if (err.has_error())
      return err;

    // Range-check that the signed value can be put in an unsigned.
    if (s64 < 0)
      return Err("This value can not be negative.");
    *out = static_cast<uint64_t>(s64);
    return Err();
  }

  // Expect everything else to be an unsigned number.
  if (number_value.GetBaseType() != BaseType::kBaseTypeUnsigned)
    return Err("This value is not the correct type.");
  return number_value.PromoteTo64(out);
}

Err ReadUint64Arg(const Command& cmd, size_t arg_index, const char* param_desc, uint64_t* out) {
  if (cmd.args().size() <= arg_index) {
    return Err(ErrType::kInput,
               fxl::StringPrintf("Not enough arguments when reading the %s.", param_desc));
  }
  Err result = StringToUint64(cmd.args()[arg_index], out);
  if (result.has_error()) {
    return Err(ErrType::kInput, fxl::StringPrintf("Invalid number \"%s\" when reading the %s.",
                                                  cmd.args()[arg_index].c_str(), param_desc));
  }
  return Err();
}

Err ParseHostPort(const std::string& in_host, const std::string& in_port, std::string* out_host,
                  uint16_t* out_port) {
  if (in_host.empty())
    return Err(ErrType::kInput, "No host component specified.");
  if (in_port.empty())
    return Err(ErrType::kInput, "No port component specified.");

  // Trim brackets from the host name for IPv6 addresses.
  if (in_host.front() == '[' && in_host.back() == ']')
    *out_host = in_host.substr(1, in_host.size() - 2);
  else
    *out_host = in_host;

  // Re-use paranoid int64 parsing.
  uint64_t port64;
  Err err = StringToUint64(in_port, &port64);
  if (err.has_error())
    return err;
  if (port64 == 0 || port64 > std::numeric_limits<uint16_t>::max())
    return Err(ErrType::kInput, "Port value out of range.");
  *out_port = static_cast<uint16_t>(port64);

  return Err();
}

Err ParseHostPort(const std::string& input, std::string* out_host, uint16_t* out_port) {
  // Separate based on the last colon.
  size_t colon = input.rfind(':');
  if (colon == std::string::npos)
    return Err(ErrType::kInput, "Expected colon to separate host/port.");

  // If the host has a colon in it, it could be an IPv6 address. In this case,
  // require brackets around it to differentiate the case where people
  // supplied an IPv6 address and we just picked out the last component above.
  std::string host = input.substr(0, colon);
  if (host.empty())
    return Err(ErrType::kInput, "No host component specified.");
  if (host.find(':') != std::string::npos) {
    if (host.front() != '[' || host.back() != ']') {
      return Err(ErrType::kInput,
                 "For IPv6 addresses use either: \"[::1]:1234\"\n"
                 "or the two-parameter form: \"::1 1234");
    }
  }

  std::string port = input.substr(colon + 1);

  return ParseHostPort(host, port, out_host, out_port);
}

std::string ThreadStateToString(debug_ipc::ThreadRecord::State state,
                                debug_ipc::ThreadRecord::BlockedReason blocked_reason) {
  // Blocked can have many cases, so we handle it separately.
  if (state != debug_ipc::ThreadRecord::State::kBlocked)
    return debug_ipc::ThreadRecord::StateToString(state);

  FXL_DCHECK(blocked_reason != debug_ipc::ThreadRecord::BlockedReason::kNotBlocked)
      << "A blocked thread has to have a valid reason.";
  return fxl::StringPrintf("Blocked (%s)",
                           debug_ipc::ThreadRecord::BlockedReasonToString(blocked_reason));
}

std::string BreakpointScopeToString(const ConsoleContext* context,
                                    const BreakpointSettings& settings) {
  switch (settings.scope) {
    case BreakpointSettings::Scope::kSystem:
      return "Global";
    case BreakpointSettings::Scope::kTarget:
      return fxl::StringPrintf("pr %d", context->IdForTarget(settings.scope_target));
    case BreakpointSettings::Scope::kThread:
      return fxl::StringPrintf(
          "pr %d t %d", context->IdForTarget(settings.scope_thread->GetProcess()->GetTarget()),
          context->IdForThread(settings.scope_thread));
  }
  FXL_NOTREACHED();
  return std::string();
}

std::string BreakpointStopToString(BreakpointSettings::StopMode mode) {
  switch (mode) {
    case BreakpointSettings::StopMode::kNone:
      return "None";
    case BreakpointSettings::StopMode::kThread:
      return "Thread";
    case BreakpointSettings::StopMode::kProcess:
      return "Process";
    case BreakpointSettings::StopMode::kAll:
      return "All";
  }
  FXL_NOTREACHED();
  return std::string();
}

const char* BreakpointEnabledToString(bool enabled) { return enabled ? "Enabled" : "Disabled"; }

std::string DescribeThread(const ConsoleContext* context, const Thread* thread) {
  return fxl::StringPrintf(
      "Thread %d [%s] koid=%" PRIu64 " %s", context->IdForThread(thread),
      ThreadStateToString(thread->GetState(), thread->GetBlockedReason()).c_str(),
      thread->GetKoid(), thread->GetName().c_str());
}

OutputBuffer FormatBreakpoint(const ConsoleContext* context, const Breakpoint* breakpoint) {
  BreakpointSettings settings = breakpoint->GetSettings();

  std::string scope = BreakpointScopeToString(context, settings);
  std::string stop = BreakpointStopToString(settings.stop_mode);
  const char* enabled = BreakpointEnabledToString(settings.enabled);
  const char* type = BreakpointTypeToString(settings.type);
  OutputBuffer location = FormatInputLocation(settings.location);

  OutputBuffer result("Breakpoint ");
  result.Append(Syntax::kSpecial, fxl::StringPrintf("%d", context->IdForBreakpoint(breakpoint)));
  result.Append(fxl::StringPrintf(" (%s) on %s, %s, stop=%s, @ ", type, scope.c_str(), enabled,
                                  stop.c_str()));

  result.Append(std::move(location));
  return result;
}

OutputBuffer FormatInputLocation(const InputLocation& location) {
  switch (location.type) {
    case InputLocation::Type::kNone:
      return OutputBuffer(Syntax::kComment, "<no location>");
    case InputLocation::Type::kLine:
      // Don't pass a TargetSymbols to DescribeFileLine because we always want
      // the full file name as passed-in by the user (as this is an "input"
      // location object). It is surprising if the debugger deletes some input.
      return OutputBuffer(DescribeFileLine(nullptr, location.line));
    case InputLocation::Type::kSymbol:
      return FormatIdentifier(location.symbol, true);
    case InputLocation::Type::kAddress:
      return OutputBuffer(fxl::StringPrintf("0x%" PRIx64, location.address));
  }
  FXL_NOTREACHED();
  return OutputBuffer();
}

OutputBuffer FormatIdentifier(const Identifier& identifier, bool bold_last) {
  return FormatIdentifier(ToParsedIdentifier(identifier), bold_last);
}

// This annoyingly duplicates Identifier::GetName but is required to get
// syntax highlighting for all the components.
OutputBuffer FormatIdentifier(const ParsedIdentifier& identifier, bool bold_last) {
  OutputBuffer result;
  if (identifier.qualification() == IdentifierQualification::kGlobal)
    result.Append(identifier.GetSeparator());

  const auto& comps = identifier.components();
  for (size_t i = 0; i < comps.size(); i++) {
    const auto& comp = comps[i];
    if (i > 0)
      result.Append(identifier.GetSeparator());

    // Name.
    if (bold_last && i == comps.size() - 1)
      result.Append(Syntax::kHeading, comp.name());
    else
      result.Append(Syntax::kNormal, comp.name());

    // Template.
    if (comp.has_template()) {
      std::string t_string("<");

      for (size_t t_i = 0; t_i < comp.template_contents().size(); t_i++) {
        if (t_i > 0)
          t_string += ", ";
        t_string += comp.template_contents()[t_i];
      }

      t_string.push_back('>');
      result.Append(Syntax::kComment, std::move(t_string));
    }
  }

  return result;
}

OutputBuffer FormatLocation(const TargetSymbols* optional_target_symbols, const Location& loc,
                            bool always_show_address, bool always_show_types) {
  if (!loc.is_valid())
    return OutputBuffer("<invalid address>");
  if (!loc.has_symbols())
    return OutputBuffer(fxl::StringPrintf("0x%" PRIx64, loc.address()));

  OutputBuffer result;
  if (always_show_address) {
    result = OutputBuffer(Syntax::kComment, fxl::StringPrintf("0x%" PRIx64 ", ", loc.address()));
  }

  const Function* func = loc.symbol().Get()->AsFunction();
  if (func) {
    OutputBuffer func_output = FormatFunctionName(func, always_show_types);
    if (!func_output.empty()) {
      result.Append(std::move(func_output));
      if (loc.file_line().is_valid()) {
        // Separator between function and file/line.
        result.Append(" " + GetBullet() + " ");
      } else {
        // Check if the address is inside a function and show the offset.
        AddressRange function_range = func->GetFullRange(loc.symbol_context());
        if (function_range.InRange(loc.address())) {
          // Inside a function but no file/line known. Show the offset.
          result.Append(fxl::StringPrintf(" + 0x%" PRIx64, loc.address() - function_range.begin()));
          result.Append(Syntax::kComment, " (no line info)");
        }
      }
    }
  }

  if (loc.file_line().is_valid())
    result.Append(DescribeFileLine(optional_target_symbols, loc.file_line()));
  return result;
}

std::string DescribeFileLine(const TargetSymbols* optional_target_symbols,
                             const FileLine& file_line) {
  std::string result;

  // Name.
  if (file_line.file().empty()) {
    result = "?";
  } else if (!optional_target_symbols) {
    result = file_line.file();
  } else {
    result = optional_target_symbols->GetShortestUniqueFileName(file_line.file());
  }

  result.push_back(':');

  // Line.
  if (file_line.line() == 0)
    result.push_back('?');
  else
    result.append(fxl::StringPrintf("%d", file_line.line()));

  return result;
}

Err SetElementsToAdd(const std::vector<std::string>& args, AssignType* assign_type,
                     std::vector<std::string>* elements_to_set) {
  if (args.size() < 2u)
    return Err("Expected at least two arguments.");

  elements_to_set->clear();

  // Validation.
  auto& token = args[1];
  if (token == "=" || token == "+=" || token == "-=") {
    if (args.size() < 3)
      return Err("Expected a value after \"=\"");
    elements_to_set->insert(elements_to_set->end(), args.begin() + 2, args.end());
    if (token == "=") {
      *assign_type = AssignType::kAssign;
    } else if (token == "+=") {
      *assign_type = AssignType::kAppend;
    }
    if (token == "-=") {
      *assign_type = AssignType::kRemove;
    }
  } else {
    *assign_type = AssignType::kAssign;
    // We just append everything after the setting name.
    elements_to_set->insert(elements_to_set->end(), args.begin() + 1, args.end());
  }

  return Err();
}

const char* AssignTypeToString(AssignType assign_type) {
  switch (assign_type) {
    case AssignType::kAssign:
      return "Assign";
    case AssignType::kAppend:
      return "Append";
    case AssignType::kRemove:
      return "Remove";
  }

  FXL_NOTREACHED();
  return "";
}

fxl::RefPtr<EvalContext> GetEvalContextForCommand(const Command& cmd) {
  if (cmd.frame())
    return cmd.frame()->GetEvalContext();

  if (Process* process = cmd.target()->GetProcess()) {
    // Process context only.
    return fxl::MakeRefCounted<EvalContextImpl>(process->GetSymbols()->GetWeakPtr(),
                                                process->GetSymbolDataProvider(), Location());
  }

  // No context.
  return fxl::MakeRefCounted<EvalContextImpl>(
      fxl::WeakPtr<ProcessSymbols>(), fxl::MakeRefCounted<SymbolDataProvider>(), Location());
}

Err EvalCommandExpression(const Command& cmd, const char* verb,
                          fxl::RefPtr<EvalContext> eval_context, bool follow_references,
                          std::function<void(const Err& err, ExprValue value)> cb) {
  Err err = cmd.ValidateNouns({Noun::kProcess, Noun::kThread, Noun::kFrame});
  if (err.has_error())
    return err;

  // This takes one expression that may have spaces, so concatenate everything
  // the command parser has split apart back into one thing.
  //
  // If we run into limitations of this, we should add a "don't parse the args"
  // flag to the command record.
  std::string expr;
  for (const auto& cur : cmd.args()) {
    if (!expr.empty())
      expr.push_back(' ');
    expr += cur;
  }

  if (expr.empty())
    return Err("Usage: %s <expression>\nSee \"help %s\" for more.", verb, verb);

  EvalExpression(expr, std::move(eval_context), follow_references, std::move(cb));
  return Err();
}

Err EvalCommandAddressExpression(
    const Command& cmd, const char* verb, fxl::RefPtr<EvalContext> eval_context,
    std::function<void(const Err& err, uint64_t address, std::optional<uint32_t> size)> cb) {
  return EvalCommandExpression(
      cmd, verb, eval_context, true,
      [eval_context, cb = std::move(cb)](const Err& err, ExprValue value) {
        if (err.has_error()) {
          cb(err, 0, std::nullopt);
          return;
        }

        fxl::RefPtr<Type> concrete_type = value.GetConcreteType(eval_context.get());
        if (concrete_type->AsCollection()) {
          // Don't allow structs and classes that are <= 64 bits to be converted
          // to addresses.
          cb(Err("Can't convert '%s' to an address.", concrete_type->GetFullName().c_str()), 0,
             std::nullopt);
          return;
        }

        // See if there's an intrinsic size to the object being pointed to. This
        // is true for pointers. References should have been followed and
        // stripped before here.
        std::optional<uint32_t> size;
        if (auto modified = concrete_type->AsModifiedType();
            modified && modified->tag() == DwarfTag::kPointerType) {
          if (auto modified_type = modified->modified().Get()->AsType())
            size = modified_type->byte_size();
        }

        // Convert anything else <= 64 bits to a number.
        uint64_t address = 0;
        Err conversion_err = value.PromoteTo64(&address);
        cb(conversion_err, address, size);
      });
}

}  // namespace zxdb
