#ifndef ICONNECTIVITY_HPP
#define ICONNECTIVITY_HPP

#include <mesh/ConnectivityMatrix.hpp>
#include <mesh/ItemOfItemType.hpp>
#include <mesh/ItemType.hpp>

#include <memory>

class IConnectivity : public std::enable_shared_from_this<IConnectivity>
{
 protected:
  template <typename DataType, typename ItemOfItem, typename ConnectivityPtr>
  friend class SubItemValuePerItem;

  template <typename DataType, typename ItemOfItem, typename ConnectivityPtr>
  friend class SubItemArrayPerItem;

  virtual const ConnectivityMatrix& _getMatrix(const ItemType& item_type_0, const ItemType& item_type_1) const = 0;

 public:
  virtual size_t dimension() const = 0;

  std::shared_ptr<const IConnectivity>
  shared_ptr() const
  {
    return this->shared_from_this();
  }

  virtual size_t numberOfNodes() const = 0;
  virtual size_t numberOfEdges() const = 0;
  virtual size_t numberOfFaces() const = 0;
  virtual size_t numberOfCells() const = 0;

  template <ItemType item_type>
  size_t numberOf() const = delete;

  IConnectivity()                     = default;
  IConnectivity(IConnectivity&&)      = delete;
  IConnectivity(const IConnectivity&) = delete;
  virtual ~IConnectivity();
};

template <>
PUGS_INLINE size_t
IConnectivity::numberOf<ItemType::node>() const
{
  return this->numberOfNodes();
}

template <>
PUGS_INLINE size_t
IConnectivity::numberOf<ItemType::edge>() const
{
  return this->numberOfEdges();
}

template <>
PUGS_INLINE size_t
IConnectivity::numberOf<ItemType::face>() const
{
  return this->numberOfFaces();
}

template <>
PUGS_INLINE size_t
IConnectivity::numberOf<ItemType::cell>() const
{
  return this->numberOfCells();
}

#endif   // ICONNECTIVITY_HPP