#ifndef ITEM_TYPE_HPP
#define ITEM_TYPE_HPP

#include <utility>
#include <limits>
#include <string>

enum class ItemType
{
  node = 0,
  edge = 1,
  face = 2,
  cell = 3
};

inline constexpr
std::string_view itemName(const ItemType& item_type)
{
  std::string_view name;
  switch(item_type){
    case ItemType::node: {
      name = "node";
      break;
    }
    case ItemType::edge: {
      name = "edge";
      break;
    }
    case ItemType::face: {
      name = "face";
      break;
    }
    case ItemType::cell: {
      name = "cell";
      break;
    }
  }
  return name;
}

template <size_t Dimension>
struct ItemTypeId {};

template <>
struct ItemTypeId<1>
{
  inline static constexpr size_t itemTId(const ItemType& item_type) {
    size_t i = std::numeric_limits<size_t>::max();
    switch(item_type) {
      case ItemType::cell: {
        i=0;
        break;
      }
      case ItemType::edge:
      case ItemType::face:
      case ItemType::node: {
        // in 1d, faces, edges and nodes are the same
        i=1;
        break;
      }
    }
    return i;
  }
};

template <>
struct ItemTypeId<2>
{
  inline static constexpr size_t itemTId(const ItemType& item_type) {
    size_t i = std::numeric_limits<size_t>::max();
    switch(item_type) {
      case ItemType::cell: {
        i=0;
        break;
      }
      case ItemType::edge:
      case ItemType::face: {
        // in 2d, faces and edges are the same
        i=1;
        break;
      }
      case ItemType::node: {
        i=2;
        break;
      }
    }
    return i;
  }
};

template <>
struct ItemTypeId<3>
{
  inline static constexpr size_t itemTId(const ItemType& item_type) {
    size_t i = std::numeric_limits<size_t>::max();
    switch(item_type) {
      case ItemType::cell: {
        i=0;
        break;
      }
      case ItemType::edge: {
        i=1;
        break;
      }
      case ItemType::face: {
        i=2;
        break;
      }
      case ItemType::node: {
        i=3;
        break;
      }
    }
    return i;
  }
};

#endif // ITEM_TYPE_HPP