//===-- BreakpointLocationCollection.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/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"

using namespace lldb;
using namespace lldb_private;

// BreakpointLocationCollection constructor
BreakpointLocationCollection::BreakpointLocationCollection(bool preserving)
    : m_preserving_bkpts(preserving) {}

// Destructor
BreakpointLocationCollection::~BreakpointLocationCollection() = default;

void BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc) {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  BreakpointLocationSP old_bp_loc =
      FindByIDPair(bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
  if (!old_bp_loc.get()) {
    m_break_loc_collection.push_back(bp_loc);
    if (m_preserving_bkpts) {
      lldb::break_id_t bp_loc_id = bp_loc->GetID();
      Breakpoint &bkpt = bp_loc->GetBreakpoint();
      lldb::break_id_t bp_id = bkpt.GetID();
      std::pair<lldb::break_id_t, lldb::break_id_t> key =
          std::make_pair(bp_id, bp_loc_id);
      auto entry = m_preserved_bps.find(key);
      if (entry == m_preserved_bps.end())
        m_preserved_bps.emplace(key, bkpt.shared_from_this());
    }
  }
}

bool BreakpointLocationCollection::Remove(lldb::break_id_t bp_id,
                                          lldb::break_id_t bp_loc_id) {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
  if (pos != m_break_loc_collection.end()) {
    if (m_preserving_bkpts) {
      std::pair<lldb::break_id_t, lldb::break_id_t> key =
          std::make_pair(bp_id, bp_loc_id);
      auto entry = m_preserved_bps.find(key);
      if (entry == m_preserved_bps.end())
        assert(0 && "Breakpoint added to collection but not preserving map.");
      else
        m_preserved_bps.erase(entry);
    }
    m_break_loc_collection.erase(pos);
    return true;
  }
  return false;
}

class BreakpointIDPairMatches {
public:
  BreakpointIDPairMatches(lldb::break_id_t break_id,
                          lldb::break_id_t break_loc_id)
      : m_break_id(break_id), m_break_loc_id(break_loc_id) {}

  bool operator()(const BreakpointLocationSP &bp_loc) const {
    return m_break_id == bp_loc->GetBreakpoint().GetID() &&
           m_break_loc_id == bp_loc->GetID();
  }

private:
  const lldb::break_id_t m_break_id;
  const lldb::break_id_t m_break_loc_id;
};

BreakpointLocationCollection::collection::iterator
BreakpointLocationCollection::GetIDPairIterator(lldb::break_id_t break_id,
                                                lldb::break_id_t break_loc_id) {
  return llvm::find_if(
      m_break_loc_collection,                           // Search full range
      BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
}

BreakpointLocationCollection::collection::const_iterator
BreakpointLocationCollection::GetIDPairConstIterator(
    lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
  return llvm::find_if(
      m_break_loc_collection,                           // Search full range
      BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
}

BreakpointLocationSP
BreakpointLocationCollection::FindByIDPair(lldb::break_id_t break_id,
                                           lldb::break_id_t break_loc_id) {
  BreakpointLocationSP stop_sp;
  collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
  if (pos != m_break_loc_collection.end())
    stop_sp = *pos;

  return stop_sp;
}

const BreakpointLocationSP BreakpointLocationCollection::FindByIDPair(
    lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const {
  BreakpointLocationSP stop_sp;
  collection::const_iterator pos =
      GetIDPairConstIterator(break_id, break_loc_id);
  if (pos != m_break_loc_collection.end())
    stop_sp = *pos;

  return stop_sp;
}

BreakpointLocationSP BreakpointLocationCollection::GetByIndex(size_t i) {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  BreakpointLocationSP stop_sp;
  if (i < m_break_loc_collection.size())
    stop_sp = m_break_loc_collection[i];

  return stop_sp;
}

const BreakpointLocationSP
BreakpointLocationCollection::GetByIndex(size_t i) const {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  BreakpointLocationSP stop_sp;
  if (i < m_break_loc_collection.size())
    stop_sp = m_break_loc_collection[i];

  return stop_sp;
}

bool BreakpointLocationCollection::ShouldStop(
    StoppointCallbackContext *context,
    BreakpointLocationCollection &stopped_bp_locs) {
  bool shouldStop = false;
  size_t i = 0;
  size_t prev_size = GetSize();
  while (i < prev_size) {
    // ShouldStop can remove the breakpoint from the list, or even delete
    // it, so we should
    BreakpointLocationSP cur_loc_sp = GetByIndex(i);
    BreakpointLocationSP reported_loc_sp;
    BreakpointSP keep_bkpt_alive_sp = cur_loc_sp->GetBreakpoint().shared_from_this();
    // We're building up the list or which locations claim responsibility for
    // this stop.  If the location's ShouldStop defers to a facade location by
    // returning a non-null reported location, we want to use that.  Otherwise
    // use the original location.
    if (cur_loc_sp->ShouldStop(context, reported_loc_sp)) {
      if (reported_loc_sp)
        stopped_bp_locs.Add(reported_loc_sp);
      else
        stopped_bp_locs.Add(cur_loc_sp);

      shouldStop = true;
    }

    if (prev_size == GetSize())
      i++;
    prev_size = GetSize();
  }
  return shouldStop;
}

bool BreakpointLocationCollection::ValidForThisThread(Thread &thread) {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  collection::iterator pos, begin = m_break_loc_collection.begin(),
                            end = m_break_loc_collection.end();

  for (pos = begin; pos != end; ++pos) {
    if ((*pos)->ValidForThisThread(thread))
      return true;
  }
  return false;
}

bool BreakpointLocationCollection::IsInternal() const {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  collection::const_iterator pos, begin = m_break_loc_collection.begin(),
                                  end = m_break_loc_collection.end();

  bool is_internal = true;

  for (pos = begin; pos != end; ++pos) {
    if (!(*pos)->GetBreakpoint().IsInternal()) {
      is_internal = false;
      break;
    }
  }
  return is_internal;
}

void BreakpointLocationCollection::GetDescription(
    Stream *s, lldb::DescriptionLevel level) {
  std::lock_guard<std::recursive_mutex> guard(m_collection_mutex);
  collection::iterator pos, begin = m_break_loc_collection.begin(),
                            end = m_break_loc_collection.end();

  for (pos = begin; pos != end; ++pos) {
    if (pos != begin)
      s->PutChar(' ');
    (*pos)->GetDescription(s, level);
  }
}

BreakpointLocationCollection &BreakpointLocationCollection::operator=(
    const BreakpointLocationCollection &rhs) {
  if (this != &rhs) {
      std::lock(m_collection_mutex, rhs.m_collection_mutex);
      std::lock_guard<std::recursive_mutex> lhs_guard(m_collection_mutex,
                                                      std::adopt_lock);
      std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_collection_mutex,
                                                      std::adopt_lock);
      m_break_loc_collection = rhs.m_break_loc_collection;
  }
  return *this;
}
