//===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef lldb_FormattersContainer_h_
#define lldb_FormattersContainer_h_

#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <string>

#include "lldb/lldb-public.h"

#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/StringLexer.h"

namespace lldb_private {

class IFormatChangeListener {
public:
  virtual ~IFormatChangeListener() = default;

  virtual void Changed() = 0;

  virtual uint32_t GetCurrentRevision() = 0;
};

// if the user tries to add formatters for, say, "struct Foo" those will not
// match any type because of the way we strip qualifiers from typenames this
// method looks for the case where the user is adding a "class","struct","enum"
// or "union" Foo and strips the unnecessary qualifier
static inline ConstString GetValidTypeName_Impl(const ConstString &type) {
  if (type.IsEmpty())
    return type;

  std::string type_cstr(type.AsCString());
  lldb_utility::StringLexer type_lexer(type_cstr);

  type_lexer.AdvanceIf("class ");
  type_lexer.AdvanceIf("enum ");
  type_lexer.AdvanceIf("struct ");
  type_lexer.AdvanceIf("union ");

  while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
    ;

  return ConstString(type_lexer.GetUnlexed());
}

template <typename KeyType, typename ValueType> class FormattersContainer;

template <typename KeyType, typename ValueType> class FormatMap {
public:
  typedef typename ValueType::SharedPointer ValueSP;
  typedef std::map<KeyType, ValueSP> MapType;
  typedef typename MapType::iterator MapIterator;
  typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback;

  FormatMap(IFormatChangeListener *lst)
      : m_map(), m_map_mutex(), listener(lst) {}

  void Add(KeyType name, const ValueSP &entry) {
    if (listener)
      entry->GetRevision() = listener->GetCurrentRevision();
    else
      entry->GetRevision() = 0;

    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
    m_map[name] = entry;
    if (listener)
      listener->Changed();
  }

  bool 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);
    if (listener)
      listener->Changed();
    return true;
  }

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

  bool 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;
  }

  void ForEach(ForEachCallback callback) {
    if (callback) {
      std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
      MapIterator pos, end = m_map.end();
      for (pos = m_map.begin(); pos != end; pos++) {
        KeyType type = pos->first;
        if (!callback(type, pos->second))
          break;
      }
    }
  }

  uint32_t GetCount() { return m_map.size(); }

  ValueSP GetValueAtIndex(size_t index) {
    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
    MapIterator iter = m_map.begin();
    MapIterator end = m_map.end();
    while (index > 0) {
      iter++;
      index--;
      if (end == iter)
        return ValueSP();
    }
    return iter->second;
  }

  KeyType GetKeyAtIndex(size_t index) {
    std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
    MapIterator iter = m_map.begin();
    MapIterator end = m_map.end();
    while (index > 0) {
      iter++;
      index--;
      if (end == iter)
        return KeyType();
    }
    return iter->first;
  }

protected:
  MapType m_map;
  std::recursive_mutex m_map_mutex;
  IFormatChangeListener *listener;

  MapType &map() { return m_map; }

  std::recursive_mutex &mutex() { return m_map_mutex; }

  friend class FormattersContainer<KeyType, ValueType>;
  friend class FormatManager;
};

template <typename KeyType, typename ValueType> class FormattersContainer {
protected:
  typedef FormatMap<KeyType, ValueType> BackEndType;

public:
  typedef typename BackEndType::MapType MapType;
  typedef typename MapType::iterator MapIterator;
  typedef typename MapType::key_type MapKeyType;
  typedef typename MapType::mapped_type MapValueType;
  typedef typename BackEndType::ForEachCallback ForEachCallback;
  typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
      SharedPointer;

  friend class TypeCategoryImpl;

  FormattersContainer(std::string name, IFormatChangeListener *lst)
      : m_format_map(lst), m_name(name) {}

  void Add(const MapKeyType &type, const MapValueType &entry) {
    Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
  }

  bool Delete(ConstString type) {
    return Delete_Impl(type, static_cast<KeyType *>(nullptr));
  }

  bool Get(ValueObject &valobj, MapValueType &entry,
           lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) {
    uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
    CompilerType ast_type(valobj.GetCompilerType());
    bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
    if (ret)
      entry = MapValueType(entry);
    else
      entry = MapValueType();
    if (why)
      *why = value;
    return ret;
  }

  bool Get(ConstString type, MapValueType &entry) {
    return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
  }

  bool GetExact(ConstString type, MapValueType &entry) {
    return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
  }

  MapValueType GetAtIndex(size_t index) {
    return m_format_map.GetValueAtIndex(index);
  }

  lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
    return GetTypeNameSpecifierAtIndex_Impl(index,
                                            static_cast<KeyType *>(nullptr));
  }

  void Clear() { m_format_map.Clear(); }

  void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }

  uint32_t GetCount() { return m_format_map.GetCount(); }

protected:
  BackEndType m_format_map;
  std::string m_name;

  DISALLOW_COPY_AND_ASSIGN(FormattersContainer);

  void Add_Impl(const MapKeyType &type, const MapValueType &entry,
                lldb::RegularExpressionSP *dummy) {
    m_format_map.Add(type, entry);
  }

  void Add_Impl(const ConstString &type, const MapValueType &entry,
                ConstString *dummy) {
    m_format_map.Add(GetValidTypeName_Impl(type), entry);
  }

  bool Delete_Impl(ConstString type, ConstString *dummy) {
    return m_format_map.Delete(type);
  }

  bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) {
    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
    MapIterator pos, end = m_format_map.map().end();
    for (pos = m_format_map.map().begin(); pos != end; pos++) {
      lldb::RegularExpressionSP regex = pos->first;
      if (type.GetStringRef() == regex->GetText()) {
        m_format_map.map().erase(pos);
        if (m_format_map.listener)
          m_format_map.listener->Changed();
        return true;
      }
    }
    return false;
  }

  bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
    return m_format_map.Get(type, entry);
  }

  bool GetExact_Impl(ConstString type, MapValueType &entry,
                     ConstString *dummy) {
    return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
  }

  lldb::TypeNameSpecifierImplSP
  GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
    ConstString key = m_format_map.GetKeyAtIndex(index);
    if (key)
      return lldb::TypeNameSpecifierImplSP(
          new TypeNameSpecifierImpl(key.AsCString(), false));
    else
      return lldb::TypeNameSpecifierImplSP();
  }

  lldb::TypeNameSpecifierImplSP
  GetTypeNameSpecifierAtIndex_Impl(size_t index,
                                   lldb::RegularExpressionSP *dummy) {
    lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
    if (regex.get() == nullptr)
      return lldb::TypeNameSpecifierImplSP();
    return lldb::TypeNameSpecifierImplSP(
        new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true));
  }

  bool Get_Impl(ConstString key, MapValueType &value,
                lldb::RegularExpressionSP *dummy) {
    llvm::StringRef key_str = key.GetStringRef();
    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
    MapIterator pos, end = m_format_map.map().end();
    for (pos = m_format_map.map().begin(); pos != end; pos++) {
      lldb::RegularExpressionSP regex = pos->first;
      if (regex->Execute(key_str)) {
        value = pos->second;
        return true;
      }
    }
    return false;
  }

  bool GetExact_Impl(ConstString key, MapValueType &value,
                     lldb::RegularExpressionSP *dummy) {
    std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
    MapIterator pos, end = m_format_map.map().end();
    for (pos = m_format_map.map().begin(); pos != end; pos++) {
      lldb::RegularExpressionSP regex = pos->first;
      if (regex->GetText() == key.GetStringRef()) {
        value = pos->second;
        return true;
      }
    }
    return false;
  }

  bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
           uint32_t *reason) {
    for (const FormattersMatchCandidate &candidate : candidates) {
      if (Get(candidate.GetTypeName(), entry)) {
        if (candidate.IsMatch(entry) == false) {
          entry.reset();
          continue;
        } else {
          if (reason)
            *reason = candidate.GetReason();
          return true;
        }
      }
    }
    return false;
  }
};

} // namespace lldb_private

#endif // lldb_FormattersContainer_h_
