//===-- Broadcaster.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/Utility/Broadcaster.h"

#include "lldb/Utility/Event.h"
#include "lldb/Utility/Listener.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"

#include <algorithm>
#include <memory>
#include <utility>

#include <cassert>
#include <cstddef>

using namespace lldb;
using namespace lldb_private;

Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name)
    : m_broadcaster_sp(std::make_shared<BroadcasterImpl>(*this)),
      m_manager_sp(std::move(manager_sp)), m_broadcaster_name(name) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
  LLDB_LOG(log, "{0} Broadcaster::Broadcaster(\"{1}\")",
           static_cast<void *>(this), GetBroadcasterName());
}

Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster)
    : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(),
      m_hijacking_listeners(), m_hijacking_masks() {}

Broadcaster::~Broadcaster() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
  LLDB_LOG(log, "{0} Broadcaster::~Broadcaster(\"{1}\")",
           static_cast<void *>(this), GetBroadcasterName());

  Clear();
}

void Broadcaster::CheckInWithManager() {
  if (m_manager_sp) {
    m_manager_sp->SignUpListenersForBroadcaster(*this);
  }
}

llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4>
Broadcaster::BroadcasterImpl::GetListeners() {
  llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> listeners;
  listeners.reserve(m_listeners.size());

  for (auto it = m_listeners.begin(); it != m_listeners.end();) {
    lldb::ListenerSP curr_listener_sp(it->first.lock());
    if (curr_listener_sp && it->second) {
      listeners.emplace_back(std::move(curr_listener_sp), it->second);
      ++it;
    } else
      it = m_listeners.erase(it);
  }

  return listeners;
}

void Broadcaster::BroadcasterImpl::Clear() {
  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  // Make sure the listener forgets about this broadcaster. We do this in the
  // broadcaster in case the broadcaster object initiates the removal.
  for (auto &pair : GetListeners())
    pair.first->BroadcasterWillDestruct(&m_broadcaster);

  m_listeners.clear();
}

Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() {
  return &m_broadcaster;
}

bool Broadcaster::BroadcasterImpl::GetEventNames(
    Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const {
  uint32_t num_names_added = 0;
  if (event_mask && !m_event_names.empty()) {
    event_names_map::const_iterator end = m_event_names.end();
    for (uint32_t bit = 1u, mask = event_mask; mask != 0 && bit != 0;
         bit <<= 1, mask >>= 1) {
      if (mask & 1) {
        event_names_map::const_iterator pos = m_event_names.find(bit);
        if (pos != end) {
          if (num_names_added > 0)
            s.PutCString(", ");

          if (prefix_with_broadcaster_name) {
            s.PutCString(GetBroadcasterName());
            s.PutChar('.');
          }
          s.PutCString(pos->second);
          ++num_names_added;
        }
      }
    }
  }
  return num_names_added > 0;
}

void Broadcaster::AddInitialEventsToListener(
    const lldb::ListenerSP &listener_sp, uint32_t requested_events) {}

uint32_t
Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp,
                                          uint32_t event_mask) {
  if (!listener_sp)
    return 0;

  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  // See if we already have this listener, and if so, update its mask

  bool handled = false;

  for (auto &pair : GetListeners()) {
    if (pair.first == listener_sp) {
      handled = true;
      pair.second |= event_mask;
      m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask);
      break;
    }
  }

  if (!handled) {
    // Grant a new listener the available event bits
    m_listeners.push_back(
        std::make_pair(lldb::ListenerWP(listener_sp), event_mask));

    // Individual broadcasters decide whether they have outstanding data when a
    // listener attaches, and insert it into the listener with this method.
    m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask);
  }

  // Return the event bits that were granted to the listener
  return event_mask;
}

bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) {
  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back())
    return true;

  for (auto &pair : GetListeners()) {
    if (pair.second & event_type)
      return true;
  }
  return false;
}

bool Broadcaster::BroadcasterImpl::RemoveListener(
    lldb_private::Listener *listener, uint32_t event_mask) {
  if (!listener)
    return false;

  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);
  for (auto &pair : GetListeners()) {
    if (pair.first.get() == listener) {
      pair.second &= ~event_mask;
      return true;
    }
  }
  return false;
}

bool Broadcaster::BroadcasterImpl::RemoveListener(
    const lldb::ListenerSP &listener_sp, uint32_t event_mask) {
  return RemoveListener(listener_sp.get(), event_mask);
}

void Broadcaster::BroadcasterImpl::BroadcastEvent(EventSP &event_sp) {
  return PrivateBroadcastEvent(event_sp, false);
}

void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) {
  return PrivateBroadcastEvent(event_sp, true);
}

void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp,
                                                         bool unique) {
  // Can't add a nullptr event...
  if (!event_sp)
    return;

  // Update the broadcaster on this event
  event_sp->SetBroadcaster(&m_broadcaster);

  const uint32_t event_type = event_sp->GetType();

  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  ListenerSP hijacking_listener_sp;

  if (!m_hijacking_listeners.empty()) {
    assert(!m_hijacking_masks.empty());
    hijacking_listener_sp = m_hijacking_listeners.back();
    if ((event_type & m_hijacking_masks.back()) == 0)
      hijacking_listener_sp.reset();
  }

  if (Log *log = lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)) {
    StreamString event_description;
    event_sp->Dump(&event_description);
    LLDB_LOGF(log,
              "%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, "
              "unique =%i) hijack = %p",
              static_cast<void *>(this), GetBroadcasterName(),
              event_description.GetData(), unique,
              static_cast<void *>(hijacking_listener_sp.get()));
  }

  if (hijacking_listener_sp) {
    if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType(
                      &m_broadcaster, event_type))
      return;
    hijacking_listener_sp->AddEvent(event_sp);
  } else {
    for (auto &pair : GetListeners()) {
      if (!(pair.second & event_type))
        continue;
      if (unique && pair.first->PeekAtNextEventForBroadcasterWithType(
                        &m_broadcaster, event_type))
        continue;

      pair.first->AddEvent(event_sp);
    }
  }
}

void Broadcaster::BroadcasterImpl::BroadcastEvent(uint32_t event_type,
                                                  EventData *event_data) {
  auto event_sp = std::make_shared<Event>(event_type, event_data);
  PrivateBroadcastEvent(event_sp, false);
}

void Broadcaster::BroadcasterImpl::BroadcastEvent(
    uint32_t event_type, const lldb::EventDataSP &event_data_sp) {
  auto event_sp = std::make_shared<Event>(event_type, event_data_sp);
  PrivateBroadcastEvent(event_sp, false);
}

void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(
    uint32_t event_type, EventData *event_data) {
  auto event_sp = std::make_shared<Event>(event_type, event_data);
  PrivateBroadcastEvent(event_sp, true);
}

bool Broadcaster::BroadcasterImpl::HijackBroadcaster(
    const lldb::ListenerSP &listener_sp, uint32_t event_mask) {
  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS));
  LLDB_LOG(
      log,
      "{0} Broadcaster(\"{1}\")::HijackBroadcaster (listener(\"{2}\")={3})",
      static_cast<void *>(this), GetBroadcasterName(),
      listener_sp->m_name.c_str(), static_cast<void *>(listener_sp.get()));
  m_hijacking_listeners.push_back(listener_sp);
  m_hijacking_masks.push_back(event_mask);
  return true;
}

bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) {
  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  if (!m_hijacking_listeners.empty())
    return (event_mask & m_hijacking_masks.back()) != 0;
  return false;
}

const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() {
  if (m_hijacking_listeners.size()) {
    return m_hijacking_listeners.back()->GetName();
  }
  return nullptr;
}

void Broadcaster::BroadcasterImpl::RestoreBroadcaster() {
  std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex);

  if (!m_hijacking_listeners.empty()) {
    ListenerSP listener_sp = m_hijacking_listeners.back();
    Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS));
    LLDB_LOG(log,
             "{0} Broadcaster(\"{1}\")::RestoreBroadcaster (about to pop "
             "listener(\"{2}\")={3})",
             static_cast<void *>(this), GetBroadcasterName(),
             listener_sp->m_name.c_str(),
             static_cast<void *>(listener_sp.get()));
    m_hijacking_listeners.pop_back();
  }
  if (!m_hijacking_masks.empty())
    m_hijacking_masks.pop_back();
}

ConstString &Broadcaster::GetBroadcasterClass() const {
  static ConstString class_name("lldb.anonymous");
  return class_name;
}

bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const {
  if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) {
    return GetEventBits() < rhs.GetEventBits();
  }
  return GetBroadcasterClass() < rhs.GetBroadcasterClass();
}

BroadcasterManager::BroadcasterManager() : m_manager_mutex() {}

lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() {
  return lldb::BroadcasterManagerSP(new BroadcasterManager());
}

uint32_t BroadcasterManager::RegisterListenerForEvents(
    const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);

  collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();
  uint32_t available_bits = event_spec.GetEventBits();

  while (iter != end_iter &&
         (iter = find_if(iter, end_iter,
                         BroadcasterClassMatches(
                             event_spec.GetBroadcasterClass()))) != end_iter) {
    available_bits &= ~((*iter).first.GetEventBits());
    iter++;
  }

  if (available_bits != 0) {
    m_event_map.insert(event_listener_key(
        BroadcastEventSpec(event_spec.GetBroadcasterClass(), available_bits),
        listener_sp));
    m_listeners.insert(listener_sp);
  }

  return available_bits;
}

bool BroadcasterManager::UnregisterListenerForEvents(
    const lldb::ListenerSP &listener_sp, const BroadcastEventSpec &event_spec) {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
  bool removed_some = false;

  if (m_listeners.erase(listener_sp) == 0)
    return false;

  ListenerMatchesAndSharedBits predicate(event_spec, listener_sp);
  std::vector<BroadcastEventSpec> to_be_readded;
  uint32_t event_bits_to_remove = event_spec.GetEventBits();

  // Go through the map and delete the exact matches, and build a list of
  // matches that weren't exact to re-add:
  while (true) {
    collection::iterator iter, end_iter = m_event_map.end();
    iter = find_if(m_event_map.begin(), end_iter, predicate);
    if (iter == end_iter) {
      break;
    }
    uint32_t iter_event_bits = (*iter).first.GetEventBits();
    removed_some = true;

    if (event_bits_to_remove != iter_event_bits) {
      uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove;
      to_be_readded.emplace_back(event_spec.GetBroadcasterClass(),
                                 new_event_bits);
    }
    m_event_map.erase(iter);
  }

  // Okay now add back the bits that weren't completely removed:
  for (size_t i = 0; i < to_be_readded.size(); i++) {
    m_event_map.insert(event_listener_key(to_be_readded[i], listener_sp));
  }

  return removed_some;
}

ListenerSP BroadcasterManager::GetListenerForEventSpec(
    const BroadcastEventSpec &event_spec) const {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);

  collection::const_iterator iter, end_iter = m_event_map.end();
  iter = find_if(m_event_map.begin(), end_iter,
                 BroadcastEventSpecMatches(event_spec));
  if (iter != end_iter)
    return (*iter).second;

  return nullptr;
}

void BroadcasterManager::RemoveListener(Listener *listener) {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
  ListenerMatchesPointer predicate(listener);
  listener_collection::iterator iter = m_listeners.begin(),
                                end_iter = m_listeners.end();

  iter = std::find_if(iter, end_iter, predicate);
  if (iter != end_iter)
    m_listeners.erase(iter);

  while (true) {
    collection::iterator iter, end_iter = m_event_map.end();
    iter = find_if(m_event_map.begin(), end_iter, predicate);
    if (iter == end_iter)
      break;

    m_event_map.erase(iter);
  }
}

void BroadcasterManager::RemoveListener(const lldb::ListenerSP &listener_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
  ListenerMatches predicate(listener_sp);

  if (m_listeners.erase(listener_sp) == 0)
    return;

  while (true) {
    collection::iterator iter, end_iter = m_event_map.end();
    iter = find_if(m_event_map.begin(), end_iter, predicate);
    if (iter == end_iter)
      break;

    m_event_map.erase(iter);
  }
}

void BroadcasterManager::SignUpListenersForBroadcaster(
    Broadcaster &broadcaster) {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);

  collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end();

  while (iter != end_iter &&
         (iter = find_if(iter, end_iter,
                         BroadcasterClassMatches(
                             broadcaster.GetBroadcasterClass()))) != end_iter) {
    (*iter).second->StartListeningForEvents(&broadcaster,
                                            (*iter).first.GetEventBits());
    iter++;
  }
}

void BroadcasterManager::Clear() {
  std::lock_guard<std::recursive_mutex> guard(m_manager_mutex);
  listener_collection::iterator end_iter = m_listeners.end();

  for (listener_collection::iterator iter = m_listeners.begin();
       iter != end_iter; iter++)
    (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this());
  m_listeners.clear();
  m_event_map.clear();
}
