// 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 "garnet/bin/zxdb/console/console_context.h"

#include <inttypes.h>

#include "garnet/bin/zxdb/client/breakpoint.h"
#include "garnet/bin/zxdb/client/frame.h"
#include "garnet/bin/zxdb/client/process.h"
#include "garnet/bin/zxdb/client/session.h"
#include "garnet/bin/zxdb/client/target.h"
#include "garnet/bin/zxdb/client/thread.h"
#include "garnet/bin/zxdb/console/command.h"
#include "garnet/bin/zxdb/console/command_utils.h"
#include "garnet/bin/zxdb/console/console.h"
#include "garnet/bin/zxdb/console/format_context.h"
#include "garnet/bin/zxdb/console/output_buffer.h"
#include "garnet/bin/zxdb/symbols/location.h"
#include "garnet/public/lib/fxl/logging.h"
#include "garnet/public/lib/fxl/strings/string_printf.h"

namespace zxdb {

ConsoleContext::ConsoleContext(Session* session) : session_(session) {
  session->system().AddObserver(this);

  // Pick up any previously created targets. This will normally just be the
  // default one.
  for (Target* target : session->system().GetTargets())
    DidCreateTarget(target);

  for (JobContext* job_context : session->system().GetJobContexts())
    DidCreateJobContext(job_context);
}

ConsoleContext::~ConsoleContext() {
  // Unregister for all observers.
  session_->system().RemoveObserver(this);

  for (auto& target_pair : id_to_target_) {
    target_pair.second.target->RemoveObserver(this);

    Process* process = target_pair.second.target->GetProcess();
    if (process)
      process->RemoveObserver(this);

    for (auto& thread_pair : target_pair.second.id_to_thread)
      thread_pair.second.thread->RemoveObserver(this);
  }
}

int ConsoleContext::IdForTarget(const Target* target) const {
  const auto& found = target_to_id_.find(target);
  if (found == target_to_id_.end()) {
    FXL_NOTREACHED();
    return 0;
  }
  return found->second;
}

int ConsoleContext::IdForJobContext(const JobContext* job_context) const {
  const auto& found = job_context_to_id_.find(job_context);
  if (found == job_context_to_id_.end()) {
    FXL_NOTREACHED();
    return 0;
  }
  return found->second;
}

int ConsoleContext::IdForThread(const Thread* thread) const {
  const TargetRecord* record =
      const_cast<ConsoleContext*>(this)->GetTargetRecord(
          thread->GetProcess()->GetTarget());
  if (!record)
    return 0;

  auto found = record->thread_to_id.find(thread);
  if (found == record->thread_to_id.end()) {
    FXL_NOTREACHED();
    return 0;
  }
  return found->second;
}

int ConsoleContext::IdForFrame(const Frame* frame) const {
  // Find the frame in the thread's backtrace. We don't have to worry about
  // whether the frames have been synced, since if there is a frame here,
  // we know it's present in the thread's list.
  Thread* thread = frame->GetThread();
  const Stack& stack = thread->GetStack();
  for (size_t i = 0; i < stack.size(); i++) {
    if (stack[i] == frame)
      return static_cast<int>(i);
  }
  FXL_NOTREACHED();  // Should have found the frame.
  return 0;
}

int ConsoleContext::IdForBreakpoint(const Breakpoint* breakpoint) const {
  FXL_DCHECK(!breakpoint->IsInternal())
      << "Should not be trying to get the ID of internal breakpoints. The "
         "client layer should filter these out.";

  auto found = breakpoint_to_id_.find(breakpoint);
  if (found == breakpoint_to_id_.end()) {
    FXL_NOTREACHED();
    return 0;
  }
  return found->second;
}

void ConsoleContext::SetActiveJobContext(const JobContext* job_context) {
  auto found = job_context_to_id_.find(job_context);
  if (found == job_context_to_id_.end()) {
    FXL_NOTREACHED();
    return;
  }
  active_job_context_id_ = found->second;
}

int ConsoleContext::GetActiveJobContextId() const {
  return active_job_context_id_;
}

JobContext* ConsoleContext::GetActiveJobContext() const {
  auto found = id_to_job_context_.find(active_job_context_id_);
  if (found == id_to_job_context_.end())
    return nullptr;
  return found->second.job_context;
}

void ConsoleContext::SetActiveTarget(const Target* target) {
  auto found = target_to_id_.find(target);
  if (found == target_to_id_.end()) {
    FXL_NOTREACHED();
    return;
  }
  active_target_id_ = found->second;
}

int ConsoleContext::GetActiveTargetId() const { return active_target_id_; }

Target* ConsoleContext::GetActiveTarget() const {
  auto found = id_to_target_.find(active_target_id_);
  if (found == id_to_target_.end())
    return nullptr;
  return found->second.target;
}

void ConsoleContext::SetActiveThreadForTarget(const Thread* thread) {
  TargetRecord* record = GetTargetRecord(thread->GetProcess()->GetTarget());
  if (!record)
    return;

  auto found = record->thread_to_id.find(thread);
  if (found == record->thread_to_id.end()) {
    FXL_NOTREACHED();
    return;
  }
  record->active_thread_id = found->second;
}

int ConsoleContext::GetActiveThreadIdForTarget(const Target* target) {
  const TargetRecord* record = GetTargetRecord(target);
  if (!record) {
    FXL_NOTREACHED();
    return 0;
  }
  return record->active_thread_id;
}

void ConsoleContext::SetActiveFrameForThread(const Frame* frame) {
  ThreadRecord* record = GetThreadRecord(frame->GetThread());
  if (!record) {
    FXL_NOTREACHED();
    return;
  }
  record->active_frame_id = IdForFrame(frame);
}

void ConsoleContext::SetActiveFrameIdForThread(const Thread* thread, int id) {
  ThreadRecord* record = GetThreadRecord(thread);
  if (!record) {
    FXL_NOTREACHED();
    return;
  }
  record->active_frame_id = id;
}

int ConsoleContext::GetActiveFrameIdForThread(const Thread* thread) const {
  const ThreadRecord* record = GetThreadRecord(thread);
  if (!record) {
    FXL_NOTREACHED();
    return 0;
  }

  // Should be a valid frame index in the thread (or no frames and == 0).
  FXL_DCHECK((thread->GetStack().empty() &&
              record->active_frame_id == 0) ||
             (record->active_frame_id >= 0 &&
              record->active_frame_id <
                  static_cast<int>(thread->GetStack().size())));
  return record->active_frame_id;
}

void ConsoleContext::SetActiveBreakpoint(const Breakpoint* breakpoint) {
  int id = IdForBreakpoint(breakpoint);
  if (id != 0)
    active_breakpoint_id_ = id;
}

int ConsoleContext::GetActiveBreakpointId() const {
  return active_breakpoint_id_;
}

Breakpoint* ConsoleContext::GetActiveBreakpoint() const {
  if (active_breakpoint_id_ == 0)
    return nullptr;
  auto found = id_to_breakpoint_.find(active_breakpoint_id_);
  if (found == id_to_breakpoint_.end()) {
    FXL_NOTREACHED();
    return nullptr;
  }
  return found->second;
}

SourceAffinity ConsoleContext::GetSourceAffinityForThread(
    const Thread* thread) const {
  const ThreadRecord* record = GetThreadRecord(thread);
  if (!record)
    return SourceAffinity::kSource;
  return record->source_affinity;
}

void ConsoleContext::SetSourceAffinityForThread(
    const Thread* thread, SourceAffinity source_affinity) {
  if (source_affinity == SourceAffinity::kNone)
    return;  // Don't change anything, previous command still stands.

  ThreadRecord* record = GetThreadRecord(thread);
  if (!record)
    return;
  record->source_affinity = source_affinity;
}

void ConsoleContext::OutputThreadContext(
    const Thread* thread, debug_ipc::NotifyException::Type type,
    const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) const {
  Target* target = thread->GetProcess()->GetTarget();

  Console* console = Console::get();
  OutputBuffer out;

  // Only print out the process when there's more than one.
  if (id_to_target_.size() > 1)
    out.Append(fxl::StringPrintf("Process %d ", IdForTarget(target)));
  out.Append(fxl::StringPrintf("Thread %d stopped ", IdForThread(thread)));

  // Skip the exception reason for the debugger breakpoints because they
  // mostly add noise.
  if (!hit_breakpoints.empty()) {
    out.Append(DescribeHitBreakpoints(hit_breakpoints));
  } else if (type != debug_ipc::NotifyException::Type::kNone &&
             type != debug_ipc::NotifyException::Type::kHardware &&
             type != debug_ipc::NotifyException::Type::kSingleStep &&
             type != debug_ipc::NotifyException::Type::kSoftware) {
    // Show exception type for non-debug exceptions. Most debug exceptions
    // are generated by the debugger internally so adds noise.
    out.Append(fxl::StringPrintf(
        "on %s exception ", debug_ipc::NotifyException::TypeToString(type)));
  }

  // Frame (current position will always be frame 0).
  const Stack& stack = thread->GetStack();
  FXL_DCHECK(!stack.empty());
  const Location& location = stack[0]->GetLocation();
  out.Append("at ");
  out.Append(FormatLocation(location, false, false));
  if (location.has_symbols()) {
    out.Append("\n");
  } else {
    out.Append(" (no symbol info)\n");
  }
  console->Output(std::move(out));
  Err err = OutputSourceContext(thread->GetProcess(), location,
                                GetSourceAffinityForThread(thread));
  if (err.has_error())
    console->Output(err);
}

Err ConsoleContext::FillOutCommand(Command* cmd) const {
  // JobContext.
  Err result = FillOutJobContext(cmd);
  if (result.has_error())
    return result;

  // Target.
  const TargetRecord* target_record = nullptr;
  result = FillOutTarget(cmd, &target_record);
  if (result.has_error())
    return result;

  // Thread.
  const ThreadRecord* thread_record = nullptr;
  result = FillOutThread(cmd, target_record, &thread_record);
  if (result.has_error())
    return result;

  // Frame.
  result = FillOutFrame(cmd, thread_record);
  if (result.has_error())
    return result;

  // Breakpoint.
  result = FillOutBreakpoint(cmd);
  if (result.has_error())
    return result;

  return Err();
}

void ConsoleContext::DidCreateTarget(Target* target) {
  target->AddObserver(this);

  int new_id = next_target_id_;
  next_target_id_++;

  TargetRecord record;
  record.target_id = new_id;
  record.target = target;

  id_to_target_[new_id] = std::move(record);
  target_to_id_[target] = new_id;

  // Set the active target only if there's none already.
  if (active_target_id_ == 0)
    active_target_id_ = new_id;
}

void ConsoleContext::DidCreateJobContext(JobContext* job_context) {
  // TODO(anmittal): Add observer if required.
  int new_id = next_job_context_id_;
  next_job_context_id_++;

  JobContextRecord record;
  record.job_context_id = new_id;
  record.job_context = job_context;

  id_to_job_context_[new_id] = std::move(record);
  job_context_to_id_[job_context] = new_id;

  // Set the active job_context only if there's none already.
  if (active_job_context_id_ == 0)
    active_job_context_id_ = new_id;
}

void ConsoleContext::WillDestroyTarget(Target* target) {
  target->RemoveObserver(this);

  TargetRecord* record = GetTargetRecord(target);
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  if (active_target_id_ == record->target_id) {
    // Need to update the default target ID.
    if (id_to_target_.empty()) {
      // This should only happen in the shutting-down case.
      active_target_id_ = 0;
    } else {
      // Just pick the first target to be the active one. It might be nice to
      // have an ordering of which one the user had selected previously in
      // case they're toggling between two.
      active_target_id_ = id_to_target_.begin()->first;
    }
  }

  // There should be no threads by the time we erase the target mapping.
  FXL_DCHECK(record->id_to_thread.empty());
  FXL_DCHECK(record->thread_to_id.empty());

  target_to_id_.erase(target);
  id_to_target_.erase(record->target_id);
  // *record is now invalid.
}

void ConsoleContext::DidCreateBreakpoint(Breakpoint* breakpoint) {
  int id = next_breakpoint_id_;
  next_breakpoint_id_++;

  id_to_breakpoint_[id] = breakpoint;
  breakpoint_to_id_[breakpoint] = id;
}

void ConsoleContext::WillDestroyBreakpoint(Breakpoint* breakpoint) {
  auto found_breakpoint = breakpoint_to_id_.find(breakpoint);
  if (found_breakpoint == breakpoint_to_id_.end()) {
    FXL_NOTREACHED();
    return;
  }
  int id = found_breakpoint->second;

  // Clear any active breakpoint if it's the deleted one.
  if (active_breakpoint_id_ == id)
    active_breakpoint_id_ = 0;

  id_to_breakpoint_.erase(id);
  breakpoint_to_id_.erase(found_breakpoint);
}

void ConsoleContext::OnSymbolIndexingInformation(const std::string& msg) {
  Console* console = Console::get();
  console->Output(OutputBuffer(Syntax::kComment, msg));
}

void ConsoleContext::DidCreateProcess(Target* target, Process* process,
                                      bool autoattached_to_new_process) {
  TargetRecord* record = GetTargetRecord(target);
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  process->AddObserver(this);

  // Restart the thread ID counting when the process starts in case this
  // target was previously running (we want to restart numbering every time).
  record->next_thread_id = 1;

  // Do the feedback.
  int target_id = IdForTarget(target);
  const char* msg = nullptr;
  Process::StartType start_type = process->start_type();
  if (start_type == Process::StartType::kAttach) {
    msg = "attached to";
  } else if (start_type == Process::StartType::kLaunch) {
    msg = "launched";
  }
  FXL_DCHECK(msg);

  OutputBuffer out;
  out.Append(fxl::StringPrintf("Process %d %s %s\n", target_id, msg,
                               process->GetName().data()));

  if (autoattached_to_new_process) {
    out.Append(Syntax::kComment,
        "  The process is currently in an initializing state. You can "
        "only set\n  pending breakpoints (symbols haven't been loaded yet) "
        "or \"continue\" (DX-912).");
  }
  Console::get()->Output(std::move(out));
}

void ConsoleContext::WillDestroyProcess(Target* target, Process* process,
                                        DestroyReason reason, int exit_code) {
  TargetRecord* record = GetTargetRecord(target);
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  Console* console = Console::get();
  std::string msg;
  switch (reason) {
    case TargetObserver::DestroyReason::kExit:
      msg = fxl::StringPrintf("Exited with code %d: ", exit_code);
      break;
    case TargetObserver::DestroyReason::kDetach:
      msg += "Detached: ";
      break;
    case TargetObserver::DestroyReason::kKill:
      msg += "Killed: ";
      break;
  }
  msg += DescribeTarget(this, target);

  console->Output(msg);
}

void ConsoleContext::DidCreateThread(Process* process, Thread* thread) {
  TargetRecord* record = GetTargetRecord(process->GetTarget());
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  thread->AddObserver(this);

  int thread_id = record->next_thread_id;
  record->next_thread_id++;

  record->id_to_thread[thread_id].thread = thread;
  record->thread_to_id[thread] = thread_id;

  // Only make a new thread the default if there is no current thread,
  // otherwise the context will be swapping out from under the user as the
  // program runs.
  if (record->active_thread_id == 0)
    record->active_thread_id = thread_id;
}

void ConsoleContext::WillDestroyThread(Process* process, Thread* thread) {
  TargetRecord* record = GetTargetRecord(process->GetTarget());
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  thread->RemoveObserver(this);

  auto found_thread_to_id = record->thread_to_id.find(thread);
  if (found_thread_to_id == record->thread_to_id.end()) {
    FXL_NOTREACHED();
    return;
  }
  int thread_id = found_thread_to_id->second;

  record->id_to_thread.erase(found_thread_to_id->second);
  record->thread_to_id.erase(found_thread_to_id);

  // Update the active thread if the currently active one is being deleted.
  if (thread_id == record->active_thread_id) {
    // Just pick the first thread to be the active one. It might be nice to
    // have an ordering of which one the user had selected previously in
    // case they're toggling between two.
    if (record->id_to_thread.empty()) {
      record->active_thread_id = 0;
    } else {
      record->active_thread_id = record->id_to_thread.begin()->first;
    }
  }
}

void ConsoleContext::OnSymbolLoadFailure(Process* process, const Err& err) {
  Console::get()->Output(err);
}

// For comparison, GDB's printout for a breakpoint hit is:
//
//   Breakpoint 1, main () at eraseme.c:4
//   4         printf("Hello\n");
//
// And LLDB's is:
//
//   * thread #1: tid = 33767, 0x000055555555463e a.out`main + 4 at
//   eraseme.c:4, name = 'a.out', stop reason = breakpoint 1.1
//       frame #0: 0x000055555555463e a.out`main + 4 at eraseme.c:4
//      1    #include <stdio.h>
//      2
//      3    int main() {
//   -> 4    printf("Hello\n");
//      5    return 1;
//      6  }
//
// When stepping, GDB prints out only the 2nd line with source info, and LLDB
// prints out the whole thing with "step over" for "stop reason".
void ConsoleContext::OnThreadStopped(
    Thread* thread, debug_ipc::NotifyException::Type type,
    const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) {
  // The stopped, process, thread, and frame should be active.
  Target* target = thread->GetProcess()->GetTarget();
  SetActiveTarget(target);
  SetActiveThreadForTarget(thread);
  SetActiveFrameIdForThread(thread, 0);

  // Show the location information.
  OutputThreadContext(thread, type, hit_breakpoints);
}

void ConsoleContext::OnThreadFramesInvalidated(Thread* thread) {
  ThreadRecord* record = GetThreadRecord(thread);
  if (!record) {
    FXL_NOTREACHED();
    return;
  }

  // Reset the active frame.
  record->active_frame_id = 0;
}

ConsoleContext::TargetRecord* ConsoleContext::GetTargetRecord(int target_id) {
  return const_cast<TargetRecord*>(
      const_cast<const ConsoleContext*>(this)->GetTargetRecord(target_id));
}

const ConsoleContext::TargetRecord* ConsoleContext::GetTargetRecord(
    int target_id) const {
  auto found_to_record = id_to_target_.find(target_id);
  if (found_to_record == id_to_target_.end()) {
    FXL_NOTREACHED();
    return nullptr;
  }
  return &found_to_record->second;
}

ConsoleContext::TargetRecord* ConsoleContext::GetTargetRecord(
    const Target* target) {
  return const_cast<TargetRecord*>(
      const_cast<const ConsoleContext*>(this)->GetTargetRecord(target));
}

const ConsoleContext::TargetRecord* ConsoleContext::GetTargetRecord(
    const Target* target) const {
  auto found_to_id = target_to_id_.find(target);
  if (found_to_id == target_to_id_.end()) {
    FXL_NOTREACHED();
    return nullptr;
  }
  return GetTargetRecord(found_to_id->second);
}

ConsoleContext::ThreadRecord* ConsoleContext::GetThreadRecord(
    const Thread* thread) {
  // Share implementation with the non-const version.
  return const_cast<ThreadRecord*>(
      const_cast<const ConsoleContext*>(this)->GetThreadRecord(thread));
}

const ConsoleContext::ThreadRecord* ConsoleContext::GetThreadRecord(
    const Thread* thread) const {
  const TargetRecord* target_record =
      GetTargetRecord(thread->GetProcess()->GetTarget());
  if (!target_record) {
    FXL_NOTREACHED();
    return nullptr;
  }

  auto found_thread_to_id = target_record->thread_to_id.find(thread);
  if (found_thread_to_id == target_record->thread_to_id.end()) {
    FXL_NOTREACHED();
    return nullptr;
  }
  int thread_id = found_thread_to_id->second;

  auto found_id_to_thread = target_record->id_to_thread.find(thread_id);
  if (found_thread_to_id == target_record->thread_to_id.end()) {
    FXL_NOTREACHED();
    return nullptr;
  }
  return &found_id_to_thread->second;
}

Err ConsoleContext::FillOutJobContext(Command* cmd) const {
  int job_context_id = cmd->GetNounIndex(Noun::kJob);
  if (job_context_id == Command::kNoIndex) {
    // No index: use the active one (may or may not exist).
    job_context_id = active_job_context_id_;
    auto found_job_context = id_to_job_context_.find(job_context_id);
    if (found_job_context == id_to_job_context_.end()) {
      // When there are no job contexts, the active ID should be 0.
      FXL_DCHECK(job_context_id == 0);
    } else {
      cmd->set_job_context(found_job_context->second.job_context);
    }
    return Err();
  }

  // Explicit index given, look it up.
  auto found_job_context = id_to_job_context_.find(job_context_id);
  if (found_job_context == id_to_job_context_.end()) {
    return Err(ErrType::kInput,
               fxl::StringPrintf("There is no job %d.", job_context_id));
  }
  cmd->set_job_context(found_job_context->second.job_context);
  return Err();
}

Err ConsoleContext::FillOutTarget(
    Command* cmd, TargetRecord const** out_target_record) const {
  int target_id = cmd->GetNounIndex(Noun::kProcess);
  if (target_id == Command::kNoIndex) {
    // No index: use the active one (which should always exist).
    target_id = active_target_id_;
    auto found_target = id_to_target_.find(target_id);
    FXL_DCHECK(found_target != id_to_target_.end());
    cmd->set_target(found_target->second.target);

    FXL_DCHECK(cmd->target());  // Default target should always exist.
    *out_target_record = GetTargetRecord(target_id);
    return Err();
  }

  // Explicit index given, look it up.
  auto found_target = id_to_target_.find(target_id);
  if (found_target == id_to_target_.end()) {
    return Err(ErrType::kInput,
               fxl::StringPrintf("There is no process %d.", target_id));
  }
  cmd->set_target(found_target->second.target);
  *out_target_record = GetTargetRecord(target_id);
  return Err();
}

Err ConsoleContext::FillOutThread(
    Command* cmd, const TargetRecord* target_record,
    ThreadRecord const** out_thread_record) const {
  int thread_id = cmd->GetNounIndex(Noun::kThread);
  const ThreadRecord* thread_record = nullptr;
  if (thread_id == Command::kNoIndex) {
    // No thread specified, use the default one.
    thread_id = target_record->active_thread_id;
    auto found_thread = target_record->id_to_thread.find(thread_id);
    if (found_thread == target_record->id_to_thread.end()) {
      // When there are no threads, the active thread ID will be 0 and that's
      // fine. But if it's nonzero, the thread should always be valid.
      FXL_DCHECK(thread_id == 0);
    } else {
      thread_record = &found_thread->second;
      cmd->set_thread(thread_record->thread);
    }
    *out_thread_record = thread_record;
    return Err();
  }

  // Explicit index given, look it up.
  auto found_thread = target_record->id_to_thread.find(thread_id);
  if (found_thread == target_record->id_to_thread.end()) {
    if (target_record->id_to_thread.empty()) {
      return Err(ErrType::kInput, "There are no threads in the process.");
    }
    return Err(
        ErrType::kInput,
        fxl::StringPrintf("There is no thread %d in the process.", thread_id));
  }

  thread_record = &found_thread->second;
  cmd->set_thread(thread_record->thread);
  *out_thread_record = thread_record;
  return Err();
}

Err ConsoleContext::FillOutFrame(Command* cmd,
                                 const ThreadRecord* thread_record) const {
  int frame_id = cmd->GetNounIndex(Noun::kFrame);
  if (frame_id == Command::kNoIndex) {
    // No index: use the active one (if any).
    if (thread_record) {
      auto& stack = thread_record->thread->GetStack();
      frame_id = thread_record->active_frame_id;
      if (frame_id >= 0 && frame_id < static_cast<int>(stack.size())) {
        cmd->set_frame(stack[frame_id]);
      } else if (!stack.empty()) {
        // Invalid frame index, default to 0th frame.
        frame_id = 0;
        cmd->set_frame(stack[0]);
      }
    }
    return Err();
  }

  // Frame index specified, use it.
  if (!thread_record)
    return Err(ErrType::kInput, "There is no thread to have frames.");

  Stack& stack = thread_record->thread->GetStack();
  if (frame_id >= 0 && frame_id < static_cast<int>(stack.size())) {
    cmd->set_frame(stack[frame_id]);
    return Err();
  }

  // Invalid frame specified. The full backtrace list is populated on
  // demand. It could be if the frames aren't synced for the thread we
  // could delay processing this command and get the frames, but we're not
  // set up to do that (this function is currently synchronous). Instead
  // if we detect the list isn't populated and the user requested one
  // that's out-of-range, request they manually sync the list.
  //
  // Check for the presence of one frame to indicate that the thread is in
  // a state to have frames at all (stopped). There will always be the
  // topmost frame in this case. If the thread is running there will be no
  // frames.
  if (stack.size() == 1 &&
      !thread_record->thread->GetStack().has_all_frames()) {
    return Err(ErrType::kInput,
               "The frames for this thread haven't been synced.\n"
               "Use \"frame\" to list the frames before selecting one to "
               "populate the frame list.");
  }
  return Err(ErrType::kInput,
             "Invalid frame index.\n"
             "Use \"frame\" to list available ones.");
}

Err ConsoleContext::FillOutBreakpoint(Command* cmd) const {
  int breakpoint_id = cmd->GetNounIndex(Noun::kBreakpoint);
  if (breakpoint_id == Command::kNoIndex) {
    // No index: use the active one (which may not exist).
    cmd->set_breakpoint(GetActiveBreakpoint());
    return Err();
  }

  // Explicit index given, look it up.
  auto found_breakpoint = id_to_breakpoint_.find(breakpoint_id);
  if (found_breakpoint == id_to_breakpoint_.end()) {
    return Err(ErrType::kInput,
               fxl::StringPrintf("There is no breakpoint %d.", breakpoint_id));
  }
  cmd->set_breakpoint(found_breakpoint->second);
  return Err();
}

std::string ConsoleContext::DescribeHitBreakpoints(
    const std::vector<fxl::WeakPtr<Breakpoint>>& hits) const {
  // Do two passes since some of the weak pointers may be gone.
  std::vector<int> ids;
  for (const auto& hit : hits) {
    if (hit)
      ids.push_back(IdForBreakpoint(hit.get()));
  }

  if (ids.empty())
    return std::string();
  if (ids.size() == 1)
    return fxl::StringPrintf("on breakpoint %d ", ids[0]);

  std::string result("on breakpoints");
  for (size_t i = 0; i < ids.size(); i++) {
    result += fxl::StringPrintf(" %d", ids[i]);
    if (i < ids.size() - 1)
      result.push_back(',');
  }
  result.push_back(' ');
  return result;
}

}  // namespace zxdb
