//===-- TypeCategoryMap.cpp ----------------------------------------*- C++
//-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/DataFormatters/TypeCategoryMap.h"

#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/Utility/Log.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes

using namespace lldb;
using namespace lldb_private;

TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
    : m_map_mutex(), listener(lst), m_map(), m_active_categories() {
  ConstString default_cs("default");
  lldb::TypeCategoryImplSP default_sp =
      lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs));
  Add(default_cs, default_sp);
  Enable(default_cs, First);
}

void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  m_map[name] = entry;
  if (listener)
    listener->Changed();
}

bool TypeCategoryMap::Delete(KeyType name) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  MapIterator iter = m_map.find(name);
  if (iter == m_map.end())
    return false;
  m_map.erase(name);
  Disable(name);
  if (listener)
    listener->Changed();
  return true;
}

bool TypeCategoryMap::Enable(KeyType category_name, Position pos) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  ValueSP category;
  if (!Get(category_name, category))
    return false;
  return Enable(category, pos);
}

bool TypeCategoryMap::Disable(KeyType category_name) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  ValueSP category;
  if (!Get(category_name, category))
    return false;
  return Disable(category);
}

bool TypeCategoryMap::Enable(ValueSP category, Position pos) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  if (category.get()) {
    Position pos_w = pos;
    if (pos == First || m_active_categories.size() == 0)
      m_active_categories.push_front(category);
    else if (pos == Last || pos == m_active_categories.size())
      m_active_categories.push_back(category);
    else if (pos < m_active_categories.size()) {
      ActiveCategoriesList::iterator iter = m_active_categories.begin();
      while (pos_w) {
        pos_w--, iter++;
      }
      m_active_categories.insert(iter, category);
    } else
      return false;
    category->Enable(true, pos);
    return true;
  }
  return false;
}

bool TypeCategoryMap::Disable(ValueSP category) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  if (category.get()) {
    m_active_categories.remove_if(delete_matching_categories(category));
    category->Disable();
    return true;
  }
  return false;
}

void TypeCategoryMap::EnableAllCategories() {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP());
  MapType::iterator iter = m_map.begin(), end = m_map.end();
  for (; iter != end; ++iter) {
    if (iter->second->IsEnabled())
      continue;
    auto pos = iter->second->GetLastEnabledPosition();
    if (pos >= sorted_categories.size()) {
      auto iter = std::find_if(
          sorted_categories.begin(), sorted_categories.end(),
          [](const ValueSP &sp) -> bool { return sp.get() == nullptr; });
      pos = std::distance(sorted_categories.begin(), iter);
    }
    sorted_categories.at(pos) = iter->second;
  }
  decltype(sorted_categories)::iterator viter = sorted_categories.begin(),
                                        vend = sorted_categories.end();
  for (; viter != vend; viter++)
    if (viter->get())
      Enable(*viter, Last);
}

void TypeCategoryMap::DisableAllCategories() {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  Position p = First;
  for (; false == m_active_categories.empty(); p++) {
    m_active_categories.front()->SetEnabledPosition(p);
    Disable(m_active_categories.front());
  }
}

void TypeCategoryMap::Clear() {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  m_map.clear();
  m_active_categories.clear();
  if (listener)
    listener->Changed();
}

bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  MapIterator iter = m_map.find(name);
  if (iter == m_map.end())
    return false;
  entry = iter->second;
  return true;
}

bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
  MapIterator iter = m_map.begin();
  MapIterator end = m_map.end();
  while (pos > 0) {
    iter++;
    pos--;
    if (iter == end)
      return false;
  }
  entry = iter->second;
  return false;
}

bool TypeCategoryMap::AnyMatches(
    ConstString type_name, TypeCategoryImpl::FormatCategoryItems items,
    bool only_enabled, const char **matching_category,
    TypeCategoryImpl::FormatCategoryItems *matching_type) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  MapIterator pos, end = m_map.end();
  for (pos = m_map.begin(); pos != end; pos++) {
    if (pos->second->AnyMatches(type_name, items, only_enabled,
                                matching_category, matching_type))
      return true;
  }
  return false;
}

lldb::TypeFormatImplSP
TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  uint32_t reason_why;
  ActiveCategoriesIterator begin, end = m_active_categories.end();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  if (log) {
    for (auto match : match_data.GetMatchesVector()) {
      log->Printf(
          "[CategoryMap::GetFormat] candidate match = %s %s %s %s reason = "
          "%" PRIu32,
          match.GetTypeName().GetCString(),
          match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
          match.DidStripReference() ? "strip-reference" : "no-strip-reference",
          match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
          match.GetReason());
    }
  }

  for (begin = m_active_categories.begin(); begin != end; begin++) {
    lldb::TypeCategoryImplSP category_sp = *begin;
    lldb::TypeFormatImplSP current_format;
    if (log)
      log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s",
                  category_sp->GetName());
    if (!category_sp->Get(match_data.GetValueObject(),
                          match_data.GetMatchesVector(), current_format,
                          &reason_why))
      continue;
    return current_format;
  }
  if (log)
    log->Printf(
        "[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
  return lldb::TypeFormatImplSP();
}

lldb::TypeSummaryImplSP
TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  uint32_t reason_why;
  ActiveCategoriesIterator begin, end = m_active_categories.end();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  if (log) {
    for (auto match : match_data.GetMatchesVector()) {
      log->Printf(
          "[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s "
          "reason = %" PRIu32,
          match.GetTypeName().GetCString(),
          match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
          match.DidStripReference() ? "strip-reference" : "no-strip-reference",
          match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
          match.GetReason());
    }
  }

  for (begin = m_active_categories.begin(); begin != end; begin++) {
    lldb::TypeCategoryImplSP category_sp = *begin;
    lldb::TypeSummaryImplSP current_format;
    if (log)
      log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s",
                  category_sp->GetName());
    if (!category_sp->Get(match_data.GetValueObject(),
                          match_data.GetMatchesVector(), current_format,
                          &reason_why))
      continue;
    return current_format;
  }
  if (log)
    log->Printf(
        "[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
  return lldb::TypeSummaryImplSP();
}

#ifndef LLDB_DISABLE_PYTHON
lldb::SyntheticChildrenSP
TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  uint32_t reason_why;

  ActiveCategoriesIterator begin, end = m_active_categories.end();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  if (log) {
    for (auto match : match_data.GetMatchesVector()) {
      log->Printf(
          "[CategoryMap::GetSyntheticChildren] candidate match = %s %s %s %s "
          "reason = %" PRIu32,
          match.GetTypeName().GetCString(),
          match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
          match.DidStripReference() ? "strip-reference" : "no-strip-reference",
          match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
          match.GetReason());
    }
  }

  for (begin = m_active_categories.begin(); begin != end; begin++) {
    lldb::TypeCategoryImplSP category_sp = *begin;
    lldb::SyntheticChildrenSP current_format;
    if (log)
      log->Printf(
          "[CategoryMap::GetSyntheticChildren] Trying to use category %s",
          category_sp->GetName());
    if (!category_sp->Get(match_data.GetValueObject(),
                          match_data.GetMatchesVector(), current_format,
                          &reason_why))
      continue;
    return current_format;
  }
  if (log)
    log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning "
                "empty SP");
  return lldb::SyntheticChildrenSP();
}
#endif

lldb::TypeValidatorImplSP
TypeCategoryMap::GetValidator(FormattersMatchData &match_data) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  uint32_t reason_why;
  ActiveCategoriesIterator begin, end = m_active_categories.end();

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));

  if (log) {
    for (auto match : match_data.GetMatchesVector()) {
      log->Printf(
          "[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = "
          "%" PRIu32,
          match.GetTypeName().GetCString(),
          match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
          match.DidStripReference() ? "strip-reference" : "no-strip-reference",
          match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
          match.GetReason());
    }
  }

  for (begin = m_active_categories.begin(); begin != end; begin++) {
    lldb::TypeCategoryImplSP category_sp = *begin;
    lldb::TypeValidatorImplSP current_format;
    if (log)
      log->Printf("[CategoryMap::GetValidator] Trying to use category %s",
                  category_sp->GetName());
    if (!category_sp->Get(match_data.GetValueObject(),
                          match_data.GetMatchesVector(), current_format,
                          &reason_why))
      continue;
    return current_format;
  }
  if (log)
    log->Printf(
        "[CategoryMap::GetValidator] nothing found - returning empty SP");
  return lldb::TypeValidatorImplSP();
}

void TypeCategoryMap::ForEach(ForEachCallback callback) {
  if (callback) {
    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

    // loop through enabled categories in respective order
    {
      ActiveCategoriesIterator begin, end = m_active_categories.end();
      for (begin = m_active_categories.begin(); begin != end; begin++) {
        lldb::TypeCategoryImplSP category = *begin;
        if (!callback(category))
          break;
      }
    }

    // loop through disabled categories in just any order
    {
      MapIterator pos, end = m_map.end();
      for (pos = m_map.begin(); pos != end; pos++) {
        if (pos->second->IsEnabled())
          continue;
        if (!callback(pos->second))
          break;
      }
    }
  }
}

TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) {
  std::lock_guard<std::recursive_mutex> guard(m_map_mutex);

  if (index < m_map.size()) {
    MapIterator pos, end = m_map.end();
    for (pos = m_map.begin(); pos != end; pos++) {
      if (index == 0)
        return pos->second;
      index--;
    }
  }

  return TypeCategoryImplSP();
}
