//===-- BreakpointIDList.cpp ----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointIDList.h"

#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Args.h"

using namespace lldb;
using namespace lldb_private;

// class BreakpointIDList

BreakpointIDList::BreakpointIDList()
    : m_invalid_id(LLDB_INVALID_BREAK_ID, LLDB_INVALID_BREAK_ID) {}

BreakpointIDList::~BreakpointIDList() = default;

size_t BreakpointIDList::GetSize() const { return m_breakpoint_ids.size(); }

const BreakpointID &
BreakpointIDList::GetBreakpointIDAtIndex(size_t index) const {
  return ((index < m_breakpoint_ids.size()) ? m_breakpoint_ids[index]
                                            : m_invalid_id);
}

bool BreakpointIDList::RemoveBreakpointIDAtIndex(size_t index) {
  if (index >= m_breakpoint_ids.size())
    return false;

  m_breakpoint_ids.erase(m_breakpoint_ids.begin() + index);
  return true;
}

void BreakpointIDList::Clear() { m_breakpoint_ids.clear(); }

bool BreakpointIDList::AddBreakpointID(BreakpointID bp_id) {
  m_breakpoint_ids.push_back(bp_id);

  return true; // We don't do any verification in this function, so always
               // return true.
}

bool BreakpointIDList::AddBreakpointID(const char *bp_id_str) {
  auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
  if (!bp_id.hasValue())
    return false;

  m_breakpoint_ids.push_back(*bp_id);
  return true;
}

bool BreakpointIDList::FindBreakpointID(BreakpointID &bp_id,
                                        size_t *position) const {
  for (size_t i = 0; i < m_breakpoint_ids.size(); ++i) {
    BreakpointID tmp_id = m_breakpoint_ids[i];
    if (tmp_id.GetBreakpointID() == bp_id.GetBreakpointID() &&
        tmp_id.GetLocationID() == bp_id.GetLocationID()) {
      *position = i;
      return true;
    }
  }

  return false;
}

bool BreakpointIDList::FindBreakpointID(const char *bp_id_str,
                                        size_t *position) const {
  auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
  if (!bp_id.hasValue())
    return false;

  return FindBreakpointID(*bp_id, position);
}

void BreakpointIDList::InsertStringArray(
    llvm::ArrayRef<const char *> string_array, CommandReturnObject &result) {
  if(string_array.empty())
    return;

  for (const char *str : string_array) {
    auto bp_id = BreakpointID::ParseCanonicalReference(str);
    if (bp_id.hasValue())
      m_breakpoint_ids.push_back(*bp_id);
  }
  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

//  This function takes OLD_ARGS, which is usually the result of breaking the
//  command string arguments into
//  an array of space-separated strings, and searches through the arguments for
//  any breakpoint ID range specifiers.
//  Any string in the array that is not part of an ID range specifier is copied
//  directly into NEW_ARGS.  If any
//  ID range specifiers are found, the range is interpreted and a list of
//  canonical breakpoint IDs corresponding to
//  all the current breakpoints and locations in the range are added to
//  NEW_ARGS.  When this function is done,
//  NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced
//  by the members of the range.

void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
                                              bool allow_locations,
                                              BreakpointName::Permissions
                                                  ::PermissionKinds purpose,
                                              CommandReturnObject &result,
                                              Args &new_args) {
  llvm::StringRef range_from;
  llvm::StringRef range_to;
  llvm::StringRef current_arg;
  std::set<std::string> names_found;

  for (size_t i = 0; i < old_args.size(); ++i) {
    bool is_range = false;

    current_arg = old_args[i].ref();
    if (!allow_locations && current_arg.contains('.')) {
      result.AppendErrorWithFormat(
          "Breakpoint locations not allowed, saw location: %s.",
          current_arg.str().c_str());
      new_args.Clear();
      return;
    }

    Status error;

    std::tie(range_from, range_to) =
        BreakpointIDList::SplitIDRangeExpression(current_arg);
    if (!range_from.empty() && !range_to.empty()) {
      is_range = true;
    } else if (BreakpointID::StringIsBreakpointName(current_arg, error)) {
      if (!error.Success()) {
        new_args.Clear();
        result.AppendError(error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return;
      } else
        names_found.insert(std::string(current_arg));
    } else if ((i + 2 < old_args.size()) &&
               BreakpointID::IsRangeIdentifier(old_args[i + 1].ref()) &&
               BreakpointID::IsValidIDExpression(current_arg) &&
               BreakpointID::IsValidIDExpression(old_args[i + 2].ref())) {
      range_from = current_arg;
      range_to = old_args[i + 2].ref();
      is_range = true;
      i = i + 2;
    } else {
      // See if user has specified id.*
      llvm::StringRef tmp_str = old_args[i].ref();
      size_t pos = tmp_str.find('.');
      if (pos != llvm::StringRef::npos) {
        llvm::StringRef bp_id_str = tmp_str.substr(0, pos);
        if (BreakpointID::IsValidIDExpression(bp_id_str) &&
            tmp_str[pos + 1] == '*' && tmp_str.size() == (pos + 2)) {

          BreakpointSP breakpoint_sp;
          auto bp_id = BreakpointID::ParseCanonicalReference(bp_id_str);
          if (bp_id.hasValue())
            breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID());
          if (!breakpoint_sp) {
            new_args.Clear();
            result.AppendErrorWithFormat("'%d' is not a valid breakpoint ID.\n",
                                         bp_id->GetBreakpointID());
            result.SetStatus(eReturnStatusFailed);
            return;
          }
          const size_t num_locations = breakpoint_sp->GetNumLocations();
          for (size_t j = 0; j < num_locations; ++j) {
            BreakpointLocation *bp_loc =
                breakpoint_sp->GetLocationAtIndex(j).get();
            StreamString canonical_id_str;
            BreakpointID::GetCanonicalReference(
                &canonical_id_str, bp_id->GetBreakpointID(), bp_loc->GetID());
            new_args.AppendArgument(canonical_id_str.GetString());
          }
        }
      }
    }

    if (!is_range) {
      new_args.AppendArgument(current_arg);
      continue;
    }

    auto start_bp = BreakpointID::ParseCanonicalReference(range_from);
    auto end_bp = BreakpointID::ParseCanonicalReference(range_to);

    if (!start_bp.hasValue() ||
        !target->GetBreakpointByID(start_bp->GetBreakpointID())) {
      new_args.Clear();
      result.AppendErrorWithFormat("'%s' is not a valid breakpoint ID.\n",
                                   range_from.str().c_str());
      result.SetStatus(eReturnStatusFailed);
      return;
    }

    if (!end_bp.hasValue() ||
        !target->GetBreakpointByID(end_bp->GetBreakpointID())) {
      new_args.Clear();
      result.AppendErrorWithFormat("'%s' is not a valid breakpoint ID.\n",
                                   range_to.str().c_str());
      result.SetStatus(eReturnStatusFailed);
      return;
    }
    break_id_t start_bp_id = start_bp->GetBreakpointID();
    break_id_t start_loc_id = start_bp->GetLocationID();
    break_id_t end_bp_id = end_bp->GetBreakpointID();
    break_id_t end_loc_id = end_bp->GetLocationID();
    if (((start_loc_id == LLDB_INVALID_BREAK_ID) &&
            (end_loc_id != LLDB_INVALID_BREAK_ID)) ||
        ((start_loc_id != LLDB_INVALID_BREAK_ID) &&
         (end_loc_id == LLDB_INVALID_BREAK_ID))) {
      new_args.Clear();
      result.AppendError("Invalid breakpoint id range:  Either "
                         "both ends of range must specify"
                         " a breakpoint location, or neither can "
                         "specify a breakpoint location.");
      result.SetStatus(eReturnStatusFailed);
      return;
    }

    // We have valid range starting & ending breakpoint IDs.  Go through all
    // the breakpoints in the target and find all the breakpoints that fit into
    // this range, and add them to new_args.

    // Next check to see if we have location id's.  If so, make sure the
    // start_bp_id and end_bp_id are for the same breakpoint; otherwise we have
    // an illegal range: breakpoint id ranges that specify bp locations are NOT
    // allowed to cross major bp id numbers.

    if ((start_loc_id != LLDB_INVALID_BREAK_ID) ||
        (end_loc_id != LLDB_INVALID_BREAK_ID)) {
      if (start_bp_id != end_bp_id) {
        new_args.Clear();
        result.AppendErrorWithFormat(
            "Invalid range: Ranges that specify particular breakpoint "
            "locations"
            " must be within the same major breakpoint; you specified two"
            " different major breakpoints, %d and %d.\n",
            start_bp_id, end_bp_id);
        result.SetStatus(eReturnStatusFailed);
        return;
      }
    }

    const BreakpointList &breakpoints = target->GetBreakpointList();
    const size_t num_breakpoints = breakpoints.GetSize();
    for (size_t j = 0; j < num_breakpoints; ++j) {
      Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(j).get();
      break_id_t cur_bp_id = breakpoint->GetID();

      if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))
        continue;

      const size_t num_locations = breakpoint->GetNumLocations();

      if ((cur_bp_id == start_bp_id) &&
          (start_loc_id != LLDB_INVALID_BREAK_ID)) {
        for (size_t k = 0; k < num_locations; ++k) {
          BreakpointLocation *bp_loc = breakpoint->GetLocationAtIndex(k).get();
          if ((bp_loc->GetID() >= start_loc_id) &&
              (bp_loc->GetID() <= end_loc_id)) {
            StreamString canonical_id_str;
            BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,
                                                bp_loc->GetID());
            new_args.AppendArgument(canonical_id_str.GetString());
          }
        }
      } else if ((cur_bp_id == end_bp_id) &&
                 (end_loc_id != LLDB_INVALID_BREAK_ID)) {
        for (size_t k = 0; k < num_locations; ++k) {
          BreakpointLocation *bp_loc = breakpoint->GetLocationAtIndex(k).get();
          if (bp_loc->GetID() <= end_loc_id) {
            StreamString canonical_id_str;
            BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,
                                                bp_loc->GetID());
            new_args.AppendArgument(canonical_id_str.GetString());
          }
        }
      } else {
        StreamString canonical_id_str;
        BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,
                                            LLDB_INVALID_BREAK_ID);
        new_args.AppendArgument(canonical_id_str.GetString());
      }
    }
  }

  // Okay, now see if we found any names, and if we did, add them:
  if (target && !names_found.empty()) {
    Status error;
    // Remove any names that aren't visible for this purpose:
    auto iter = names_found.begin();
    while (iter != names_found.end()) {
      BreakpointName *bp_name = target->FindBreakpointName(ConstString(*iter),
                                                           true,
                                                           error);
      if (bp_name && !bp_name->GetPermission(purpose))
        iter = names_found.erase(iter);
      else
        iter++;
    }
    
    if (!names_found.empty()) {
      for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) {
        for (std::string name : names_found) {
          if (bkpt_sp->MatchesName(name.c_str())) {
            StreamString canonical_id_str;
            BreakpointID::GetCanonicalReference(
                &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);
            new_args.AppendArgument(canonical_id_str.GetString());
          }
        }
      }
    }
  }

  result.SetStatus(eReturnStatusSuccessFinishNoResult);
}

std::pair<llvm::StringRef, llvm::StringRef>
BreakpointIDList::SplitIDRangeExpression(llvm::StringRef in_string) {
  for (auto specifier_str : BreakpointID::GetRangeSpecifiers()) {
    size_t idx = in_string.find(specifier_str);
    if (idx == llvm::StringRef::npos)
      continue;
    llvm::StringRef right1 = in_string.drop_front(idx);

    llvm::StringRef from = in_string.take_front(idx);
    llvm::StringRef to = right1.drop_front(specifier_str.size());

    if (BreakpointID::IsValidIDExpression(from) &&
        BreakpointID::IsValidIDExpression(to)) {
      return std::make_pair(from, to);
    }
  }

  return std::pair<llvm::StringRef, llvm::StringRef>();
}
