#ifndef MESH_HPP
#define MESH_HPP

#include <algebra/TinyVector.hpp>
#include <mesh/IMesh.hpp>
#include <mesh/ItemValue.hpp>

#include <memory>

template <typename ConnectivityType>
class Mesh final : public IMesh
{
 public:
  using Connectivity = ConnectivityType;

  static constexpr size_t Dimension = ConnectivityType::Dimension;
  using Rd                          = TinyVector<Dimension>;

 private:
  const std::shared_ptr<const Connectivity> m_connectivity;
  NodeValue<const Rd> m_xr;

 public:
  PUGS_INLINE
  size_t
  dimension() const
  {
    return Dimension;
  }

  PUGS_INLINE
  const Connectivity&
  connectivity() const
  {
    return *m_connectivity;
  }

  PUGS_INLINE
  const auto&
  shared_connectivity() const
  {
    return m_connectivity;
  }

  PUGS_INLINE
  size_t
  numberOfNodes() const
  {
    return m_connectivity->numberOfNodes();
  }

  PUGS_INLINE
  size_t
  numberOfEdges() const
  {
    return m_connectivity->numberOfEdges();
  }

  PUGS_INLINE
  size_t
  numberOfFaces() const
  {
    return m_connectivity->numberOfFaces();
  }

  PUGS_INLINE
  size_t
  numberOfCells() const
  {
    return m_connectivity->numberOfCells();
  }

  template <ItemType item_type>
  PUGS_INLINE size_t
  numberOf() const
  {
    return m_connectivity->template numberOf<item_type>();
  }

  PUGS_INLINE
  const NodeValue<const Rd>&
  xr() const
  {
    return m_xr;
  }

  PUGS_INLINE
  Mesh(const std::shared_ptr<const Connectivity>& connectivity, NodeValue<Rd>& xr)
    : m_connectivity{connectivity}, m_xr{xr}
  {
    ;
  }

  Mesh() = delete;

  ~Mesh()
  {
    ;
  }
};

#endif   // MESH_HPP