#pragma once

namespace perlbind { namespace detail {

struct usertype_counter
{
  static std::size_t next_id()
  {
    static std::size_t counter = 0;
    return counter++;
  }
};

template <typename T>
struct usertype
{
  static std::string id()
  {
    static std::size_t id = usertype_counter::next_id();
    return std::to_string(id);
  }
};

namespace typemap
{
  // type names are stored in a hash on interpreter when registered with
  // unique id keys generated by usertype counter
  inline hash get(PerlInterpreter* my_perl)
  {
    HV* hv = get_hv("__perlbind::typemap", GV_ADD);
    return reinterpret_cast<HV*>(SvREFCNT_inc(hv));
  }

  template <typename T>
  const char* get_name(PerlInterpreter* my_perl)
  {
    auto typemap = detail::typemap::get(my_perl);
    auto type_id = detail::template usertype<T>::id();

    return typemap.exists(type_id) ? typemap[type_id].c_str() : nullptr;
  }
} // namespace typemap

} // namespace detail
} // namespace perlbind
